Ich habe eine klavierähnliche Anwendung, und wenn ich die Klaviertaste drücke, spielt sie einen Ton. In meiner App habe ich meinen eigenen Sinusgenerator geschrieben. App ist in Qt geschrieben. Ich denke, dass dieses Problem mit PortAudio ist, aber ich kann keine Lösung dafür finden.PortAudio: kurzes Rauschen am Anfang und am Ende des Sounds
ich für Sie aufgezeichnet haben, wie mein Problem klingt: https://vocaroo.com/i/s1yiWjaJffTU
Und hier ist mein Generator Klasse:
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;
}
Wenn ich die Taste drücke, Funktion
void SoundEngine::generateSine()
läuft - es erzeugt Sound. Wenn ich die Taste loslasse, entfernt die Methode
den Ton.
Da es nicht wirklich die Wiedergabe von Audio ist, sondern eine einfache Sinuswellengenerierung, kann man einfach nicht sofort aufhören zu stoppen, sondern es zu stoppen, nächstes Mal, wenn die Amplitude Null ist. – dtech
Das hilft nicht, da es einen sehr kurzen Zeitabstand zwischen einem Spitzenwert und einer Null gibt (tatsächlich gibt es 3 Nullen für jeden Zyklus), so dass Sie am Ende immer noch einen Pop hören. Die Lösung ändert die Umhüllung, wie ich erklärte. –
Ja, Sie haben recht, ich dachte aus irgendeinem Grund viel tiefer als hörbare Frequenzen. Das Beenden eines Zyklus in solch hohen Frequenzen wird nicht mit dem abrupten Amplitudenabfall fertig werden. – dtech