2017-12-11 7 views
0

ピアノ風のアプリケーションがあり、ピアノキーを押すと音が鳴ります。私のアプリでは、私は自分自身の正弦波ジェネレータを書いた。アプリはQtで書かれています。問題はportAudioだと思いますが、私はこれに対する解決策を見つけることができません。PortAudio:音の始まりと終わりの短い騒音

私は私の問題は、どのように聞こえるか、あなたのために記録してきました

https://vocaroo.com/i/s1yiWjaJffTU

そして、ここでは私のジェネレータクラスです:

soundEngine.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 

soundEngine.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

モデレータ注意:この質問は、このフォーラムよりもdsp.stackexchangeの方が多いようです。

サウンドやPortAudioに問題はありません。最後に聞いている音は、オーディオが突然停止した結果です。期間全体を通じて一定の振幅を持つサウンドの次のイメージを見てください。このサウンドには、最後にポップ音が鳴ります。我々はそれが画像#2の音に似ているように(画像#1と同じ音)の波形のエンベロープを修正することによって振幅を減衰させる場合

Constant amplitude throughout the sound file

逆に、我々は、任意の急激な変化を聞くことはありません最終的には音の中の音が聞こえます。

enter image description here

結論として、あなたの目標は、完全にあなたが聞いているポップを排除するためであれば、フェードアウト(またはフェードイン)、サウンド(複数可)。

+1

実際にはオーディオの再生ではなく、単純な正弦波の生成であるため、フェードアウトするのではなく、ただちに停止することはできませんが、振幅がゼロの次回に停止するようにスケジュールできます。 – dtech

+1

ピーク値とゼロとの間の時間間隔が非常に短いため(実際には1サイクルごとに3つのゼロがあるため)、助けにならないので、最後にポップ音が聞こえます。私が説明したように、ソリューションはエンベロープを変えています。 –

+1

はい、あなたは正しいです、私は何らかの理由で、可聴周波数よりはるかに低いと考えていました。このような高い周波数でサイクルを終了しても、急激な振幅低下は処理されません。 – dtech

関連する問題