Playback of created audio data has noise and occasional click on sound

I am writing an application that reproduces sound received from hardware (for example, a ring buffer filled with a sine wave with a certain frequency). Everything works fine, and I can correctly reproduce the sound created, except for periodically pressing (maybe at the end of the buffer?) And noise.

I initialize and run the buffer:

void Audiooutput::InitializeAudioParameters() { Audio_DataWritten = 0; Audio_fragments = 4; Audio_channels = 2; Audio_BufferSize = 256; Audio_Samplerate = 8000; Audio_ResamplingFactor = 1; Audio_Framesize = 2; // (SND_PCM_FORMAT_S16_LE / 8); Audio_frames = Audio_BufferSize / Audio_Framesize * Audio_fragments; snd_pcm_uframes_t size; err = snd_pcm_hw_params_any(pcmPlaybackHandle, hw_params); err = snd_pcm_hw_params_set_rate_resample(pcmPlaybackHandle, hw_params, 1); // qDebug()<<a1.sprintf(" % d \t snd_pcm_hw_params_set_rate: %s",Audio_Samplerate,snd_strerror(err)); err = snd_pcm_hw_params_set_format(pcmPlaybackHandle, hw_params, SND_PCM_FORMAT_S16_LE); err = snd_pcm_hw_params_set_channels(pcmPlaybackHandle, hw_params, Audio_channels); err = snd_pcm_hw_params_set_rate_near(pcmPlaybackHandle, hw_params, &Audio_Samplerate, 0); // qDebug()<<a1.sprintf(" % d \t snd_pcm_hw_params_set_rate: %s",Audio_Samplerate,snd_strerror(err)); if ((err = snd_pcm_hw_params_set_periods_near(pcmPlaybackHandle, hw_params, &Audio_fragments, 0)) < 0) { qDebug() << a1.sprintf("Error setting # fragments to %d: %s\n", Audio_fragments, snd_strerror(err)); } else qDebug() << a1.sprintf("setting # fragments to %d: %s\n", Audio_fragments, snd_strerror(err)); err = snd_pcm_hw_params_get_buffer_size(hw_params, &size); if ((err = snd_pcm_hw_params_set_buffer_size_near(pcmPlaybackHandle, hw_params, &Audio_frames)) < 0) { qDebug() << a1. sprintf("Error setting buffer_size %d frames: %s", Audio_frames, snd_strerror(err)); } else qDebug() << a1.sprintf("setting Buffersize to %d --> %d: %s\n", Audio_BufferSize, Audio_frames, snd_strerror(err)); Audio_BufferSize = Audio_frames; if ((err = snd_pcm_hw_params(pcmPlaybackHandle, hw_params)) < 0) { qDebug() << a1.sprintf("Error setting HW params: %s", snd_strerror(err)); } Q_ASSERT(err >= 0); } void Audiooutput::ProduceAudioOutput(int n, int mmodes, int totalMModeGates, short *sinusValue, short *cosinusValue) { for (int audioSample = 0; audioSample < n; audioSample += Audio_ResamplingFactor) { currentposition = (int)(m_Audio.generalPos % (Audio_BufferSize / 2)); if (currentposition == 0) { QueueAudioBuffer(); m_Audio.currentPos = 0; } m_Audio.generalPos++; AudioData[currentposition * 2] = (short)(sinusValue[audioSample]); AudioData[currentposition * 2 + 1] = (short)(cosinusValue[audioSample]); } } void Audiooutput::QueueAudioBuffer() { snd_pcm_prepare(pcmPlaybackHandle); Audio_DataWritten += snd_pcm_writei(pcmPlaybackHandle, AudioData, Audio_BufferSize); } 

Changing the size or fragments of the audio buffer also changes the period of pressing. Can someone help me with this problem? I also checked the first and last values. Yours is always the difference.

OS: Ubuntu 11

in details.

the amount of data received is dynamic, and the changes depend on different parameters. But I always play a role, for example. 128 values ​​or 256 or 512 ....

// I get Audiodata from the hardware (in Timerloop)

  audiobuffersize = 256; short *AudioData = new short[256]; int generalAudioSample = 0; void CollectDataFromHw() { ... int n = 0; n = GetData(buf1,buf2);//buf1 = new short[MAX_SHRT] if(n > 0) FillAudioBuffer(n,buf1,buf2) ... } ------------------------------------------- void FillAudioBuffer(int n, short*buf1, short*buf2) { for(int audioSample = 0;audioSample < n; audioSample++){ iCurrentAudioSample = (int)(generalAudioSample % (audiobuffersize/2)); if(iCurrentAudioSample == 0) { snd_pcm_writei(pcmPlaybackHandle,AudioData,audiobuffersize ); memset(AudioData,0x00,audiobuffersize*sizeof(short)); } generalAudioSample++; AudioData[iCurrentAudioSample * 2] = (short)(buf1[audioSample]; AudioData[iCurrentAudioSample * 2 +1] = (short)(buf2[audioSample]; } } 

I also changed the audio footwear. If I set it to a larger size, I have an extra Echo for clicks.

any idea? // ----------------------- problem

 snd_pcm_prepare(pcmPlaybackHandle); 

each call to this function causes a click on the sound!

+4
source share
2 answers

The resolved buffer was played several times before it was filled with data.

stupid mistake in the code .missing a parantez β†’ audio_buffersize / 2 <- - and therefore the result was very often if (iCurrentAudioSample == 0) true !!!!!

 iCurrentAudioSample = (int)(generalAudioSample % (audio_buffersize/2)); if(iCurrentAudioSample == 0) { writetoaudioStream(audiobuffer); } 
+1
source

The source code cannot be verified, but I think the high-frequency clicks that you hear are tearing sound waves. You must make sure that the cycle period (or buffer size) is a multiple of the wave period.

Check if the first and last buffer value matches (for example, +/- 1). Their distance determines the amplitude of the unwanted click.

+2
source

Source: https://habr.com/ru/post/1381079/


All Articles