代码之家  ›  专栏  ›  技术社区  ›  Lizard_Paszczyk

PortAudio:声音开始和结束时的短噪音

  •  0
  • Lizard_Paszczyk  · 技术社区  · 7 年前

    我有类似钢琴的应用程序,当我按钢琴键时,它会发出声音。在我的应用程序中,我编写了自己的正弦波发生器。应用程序是用Qt编写的。我认为这是portAudio的问题,但我找不到任何解决方案。

    我已经为您录制了我的问题的声音: https://vocaroo.com/i/s1yiWjaJffTU

    这是我的发电机课程:

    声音引擎。h类

    #ifndef SOUNDENGINE_H
    #define SOUNDENGINE_H
    
    #include <QThread>
    #include <math.h>
    #include "portaudio.h"
    
    #define SAMPLE_RATE   (44100)
    #define FRAMES_PER_BUFFER  (64)
    #define FREQUENCY 220
    
    #ifndef M_PI
    #define M_PI  (3.14159265)
    #endif
    
    #define TABLE_SIZE   (200)
    
    typedef struct
    {
        float sine[TABLE_SIZE];
        int phase;
    }
    paTestData;
    
    class SoundEngine : public QThread
    {
        Q_OBJECT
    public:
        bool turnOFF;
        void run();
        static int patestCallback( const void *inputBuffer, void *outputBuffer,unsigned long framesPerBuffer,const PaStreamCallbackTimeInfo* timeInfo,PaStreamCallbackFlags statusFlags,void *userData );
        void generateSine();
        void removeSine();
    private:
        paTestData data;
        PaStream *stream;
        PaError err;
        bool isPressed;
    };
    
    #endif // SOUNDENGINE_H
    

    声音引擎。cpp公司

    #include "soundengine.h"
    #include <QDebug>
    
    void SoundEngine::run()
    {
        PaStreamParameters outputParameters;
        int i;
        double t;
        turnOFF = false;
        isPressed = false;
    
        static unsigned long n=0;
        for( i=0; i<TABLE_SIZE; i++, n++ )
        {
            t = (double)i/(double)SAMPLE_RATE;
            data.sine[i] = 0;
            //data.sine[i] = 0.3*sin(2 * M_PI * FREQUENCY * t);
            /*data.sine[i] *= 1.0/2;
            data.sine[i] += 0.5*sin(2 * M_PI * (FREQUENCY+110) * t);
            data.sine[i] *= 2.0/3;
            data.sine[i] += (1.0/3)*sin(2 * M_PI * (FREQUENCY+60) * t);
            data.sine[i] *= 3.0/4;
            data.sine[i] += (1.0/4)*sin(2 * M_PI * (FREQUENCY+160) * t);*/
        }
        data.phase = 0;
    
        err = Pa_Initialize();
        if(err != paNoError) qDebug()<<"Błąd przy inicjalizacji strumienia:"<<Pa_GetErrorText(err);
    
        outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
        if (outputParameters.device == paNoDevice) qDebug()<<"Błąd: Brak domyślnego urządzenia wyjścia!";
    
        outputParameters.channelCount = 2;       /* stereo output */
        outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
        outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
        outputParameters.hostApiSpecificStreamInfo = NULL;
    
        err = Pa_OpenStream(
                  &stream,
                  NULL, /* no input */
                  &outputParameters,
                  SAMPLE_RATE,
                  FRAMES_PER_BUFFER,
                  paClipOff,      /*paNoFlag we won't output out of range samples so don't bother clipping them */
                  patestCallback,
                  &data );
        if(err != paNoError) qDebug()<<"Błąd przy otwieraniu strumienia:"<<Pa_GetErrorText(err);
        //err = Pa_StartStream( stream );
        if(err != paNoError) qDebug()<<"Błąd przy starcie strumienia:"<<Pa_GetErrorText(err);
    
        while (turnOFF == false) {
            Pa_Sleep(500);
        }
    
        //err = Pa_StopStream( stream );
        if(err != paNoError) qDebug()<<"Błąd przy zatrzymywaniu strumienia:"<<Pa_GetErrorText(err);
        err = Pa_CloseStream( stream );
        if(err != paNoError) qDebug()<<"Błąd przy zamykaniu strumienia:"<<Pa_GetErrorText(err);
        Pa_Terminate();
    }
    
    int SoundEngine::patestCallback(const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *timeInfo, PaStreamCallbackFlags statusFlags, void *userData)
    {
        paTestData *callData = (paTestData*)userData;
        float *out = (float*)outputBuffer;
        float sample;
        unsigned long i;
    
        (void) timeInfo; /* Prevent unused variable warnings. */
        (void) statusFlags;
        (void) inputBuffer;
    
        for( i=0; i<framesPerBuffer; i++ )
        {
            sample = callData->sine[callData->phase++];
            *out++ = sample;  /* left */
            *out++ = sample;  /* right */
            if( callData->phase >= TABLE_SIZE ) callData->phase -= TABLE_SIZE;
        }
    
        return paContinue;
    }
    
    void SoundEngine::generateSine()
    {
        if(isPressed == false)
        {
            for(int i=0; i<TABLE_SIZE; i++)
            {
                data.sine[i] += 0.3*sin(2 * M_PI * 440 * ((double)i/(double)SAMPLE_RATE));
            }
            isPressed = true;
            err = Pa_StartStream( stream );
        }
    }
    
    void SoundEngine::removeSine()
    {
        err = Pa_StopStream( stream );
        for(int i=0; i<TABLE_SIZE; i++)
        {
            data.sine[i] -= 0.3*sin(2 * M_PI * 440 * ((double)i/(double)SAMPLE_RATE));
        }
        isPressed = false;
    
    }
    

    当我按下按钮时,功能

    void SoundEngine::generateSine()
    

    正在运行-它会发出声音。当我松开按钮时,方法

    void SoundEngine::removeSine()
    

    删除声音。

    1 回复  |  直到 7 年前
        1
  •  1
  •   dsp_user    7 年前

    主持人注意:这个问题似乎更属于dsp。stackexchange比此论坛。

    你的声音和PortAudio都没有问题。您在结尾听到的声音只是音频突然停止的结果。请看下图,该声音在整个持续时间内具有恒定振幅。该声音将在最后发出砰砰声。

    Constant amplitude throughout the sound file

    相反,如果我们通过修改波形的包络(与图像#1中的声音相同)来衰减振幅,使其与图像#2中的声音相似,则我们不会听到声音在结尾处发生任何突变。

    enter image description here

    总之,如果你的目标是完全消除你听到的POP,那么就淡出(或淡入)你的声音。