refs #144 , improved SELCAL in a way that SELCAL tones will always end with 0 amplitude.

* method to write values in buffer -> writeAmplitudeToBuffer
* fixes the range from the last 0 pass so SELCAL tones will always end with 0 amplitude
This commit is contained in:
Klaus Basan
2014-02-26 02:27:31 +01:00
parent 59ff750b4a
commit a43621774b
2 changed files with 70 additions and 30 deletions

View File

@@ -157,14 +157,14 @@ namespace BlackSound
foreach(Tone t, this->m_tones) foreach(Tone t, this->m_tones)
{ {
qint64 bytesPerTone = this->m_audioFormat.sampleRate() * bytesForAllChannels * t.m_durationMs / 1000; qint64 bytesPerTone = this->m_audioFormat.sampleRate() * bytesForAllChannels * t.m_durationMs / 1000;
qint64 last0AmplitudeSample = bytesPerTone; // last sample when amplitude was 0
int sampleIndexPerTone = 0; int sampleIndexPerTone = 0;
while (bytesPerTone) while (bytesPerTone)
{ {
// http://hyperphysics.phy-astr.gsu.edu/hbase/audio/sumdif.html // http://hyperphysics.phy-astr.gsu.edu/hbase/audio/sumdif.html
// http://math.stackexchange.com/questions/164369/how-do-you-calculate-the-frequency-perceived-by-humans-of-two-sinusoidal-waves-a // http://math.stackexchange.com/questions/164369/how-do-you-calculate-the-frequency-perceived-by-humans-of-two-sinusoidal-waves-a
const double pseudoTime = double(sampleIndexPerTone % this->m_audioFormat.sampleRate()) / this->m_audioFormat.sampleRate(); const double pseudoTime = double(sampleIndexPerTone % this->m_audioFormat.sampleRate()) / this->m_audioFormat.sampleRate();
double amplitude = 0; // silence double amplitude = 0.0; // amplitude -1 -> +1 , 0 is silence
if (t.m_frequencyHz > 10) if (t.m_frequencyHz > 10)
{ {
// the combination of two frequencies actually would have 2*amplitude, // the combination of two frequencies actually would have 2*amplitude,
@@ -176,7 +176,49 @@ namespace BlackSound
qCos(M_PI * (t.m_frequencyHz - t.m_secondaryFrequencyHz) * pseudoTime); qCos(M_PI * (t.m_frequencyHz - t.m_secondaryFrequencyHz) * pseudoTime);
} }
// avoid overflow
Q_ASSERT(amplitude <= 1.0 && amplitude >= -1.0);
if (amplitude < -1.0)
amplitude = -1.0;
else if (amplitude > 1.0)
amplitude = 1.0;
else if (qAbs(amplitude) < double(1.0 / 65535))
{
amplitude = 0;
last0AmplitudeSample = bytesPerTone;
}
// generate this for all channels, usually 1 channel
for (int i = 0; i < this->m_audioFormat.channelCount(); ++i) for (int i = 0; i < this->m_audioFormat.channelCount(); ++i)
{
this->writeAmplitudeToBuffer(amplitude, bufferPointer);
bufferPointer += bytesPerSample;
bytesPerTone -= bytesPerSample;
}
++sampleIndexPerTone;
}
// fixes the range from the last 0 pass through
if (last0AmplitudeSample > 0)
{
bufferPointer -= last0AmplitudeSample;
while (last0AmplitudeSample)
{
double amplitude = 0.0; // amplitude -1 -> +1 , 0 is silence
// generate this for all channels, usually 1 channel
for (int i = 0; i < this->m_audioFormat.channelCount(); ++i)
{
this->writeAmplitudeToBuffer(amplitude, bufferPointer);
bufferPointer += bytesPerSample;
last0AmplitudeSample -= bytesPerSample;
}
}
}
}
}
void CSoundGenerator::writeAmplitudeToBuffer(const double amplitude, unsigned char *bufferPointer)
{ {
if (this->m_audioFormat.sampleSize() == 8 && this->m_audioFormat.sampleType() == QAudioFormat::UnSignedInt) if (this->m_audioFormat.sampleSize() == 8 && this->m_audioFormat.sampleType() == QAudioFormat::UnSignedInt)
{ {
@@ -204,13 +246,6 @@ namespace BlackSound
else else
qToBigEndian<qint16>(value, bufferPointer); qToBigEndian<qint16>(value, bufferPointer);
} }
bufferPointer += bytesPerSample;
bytesPerTone -= bytesPerSample;
}
++sampleIndexPerTone;
}
}
} }
bool CSoundGenerator::saveToWavFile(const QString &fileName) const bool CSoundGenerator::saveToWavFile(const QString &fileName) const
@@ -450,7 +485,6 @@ namespace BlackSound
void CSoundGenerator::playFile(qint32 volume, const QString &file, bool removeFileAfterPlaying) void CSoundGenerator::playFile(qint32 volume, const QString &file, bool removeFileAfterPlaying)
{ {
if (!QFile::exists(file)) return; if (!QFile::exists(file)) return;
QMediaPlayer *mediaPlayer = CSoundGenerator::mediaPlayer(); QMediaPlayer *mediaPlayer = CSoundGenerator::mediaPlayer();
QMediaResource mediaResource(QUrl(file), "audio"); QMediaResource mediaResource(QUrl(file), "audio");
QMediaContent media(mediaResource); QMediaContent media(mediaResource);

View File

@@ -344,6 +344,12 @@ namespace BlackSound
//! \brief save buffer to wav file //! \brief save buffer to wav file
bool saveToWavFile(const QString &fileName) const; bool saveToWavFile(const QString &fileName) const;
/*!
* \brief Write amplitude to buffer
* \param amplitude value -1 .. 1
* \param bufferPointer current buffer pointer
*/
void writeAmplitudeToBuffer(const double amplitude, unsigned char *bufferPointer);
}; };
} //namespace } //namespace