声音播放不正确,嗡嗡声而不是录制的声音 - Portaudio
Sound not properly played, buzzing sound instead of recorded sound - Portaudio
我正在尝试使用 Portaudio 录制和播放一些声音,objective 是为了创建一个简单的 voip 应用程序,所以我正在尝试将录制的数据从第一个客户端传输到第二个客户端。问题是在播放录制的声音时,我要么没有播放声音,要么声音很嗡嗡声,让我解释一下:
这是我的录音和播放回调函数:
int recordCallback(const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags, void *userData)
{
paTestData *data = (paTestData*)userData;
const SAMPLE *rptr = (const SAMPLE*)inputBuffer;
SAMPLE *wptr = &data->recordedSamples[data->frameIndex * NUM_CHANNELS];
long framesToCalc;
long i;
int finished;
unsigned long framesLeft = data->maxFrameIndex - data->frameIndex;
(void) outputBuffer;
(void) timeInfo;
(void) statusFlags;
(void) userData;
if (framesLeft < framesPerBuffer) {
framesToCalc = framesLeft;
finished = paComplete;
} else {
framesToCalc = framesPerBuffer;
finished = paContinue;
} if (inputBuffer == NULL) {
for (i = 0; i<framesToCalc; i++) {
*wptr++ = SAMPLE_SILENCE;
if (NUM_CHANNELS == 2 ) *wptr++ = SAMPLE_SILENCE;
}
} else {
for(i = 0; i<framesToCalc; i++) {
*wptr++ = *rptr++;
if( NUM_CHANNELS == 2 ) *wptr++ = *rptr++;
}
}
data->frameIndex += framesToCalc;
return finished;
}
int playCallback( const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags, void *userData )
{
paTestData *data = (paTestData*)userData;
data->frameIndex = 1;
SAMPLE *rptr = &data->recordedSamples[data->frameIndex * NUM_CHANNELS];
SAMPLE *wptr = (SAMPLE*)outputBuffer;
unsigned int i = 0;
int finished;
unsigned int framesLeft = data->maxFrameIndex - data->frameIndex;
(void) inputBuffer; /* Prevent unused variable warnings. */
(void) timeInfo;
(void) statusFlags;
(void) userData;
if (framesLeft < framesPerBuffer) {
for (i = 0; i < framesLeft; i++) {
*wptr++ = *rptr++;
if (NUM_CHANNELS == 2) *wptr++ = *rptr++;
} for (; i < framesPerBuffer; i++) {
*wptr++ = 0;
if (NUM_CHANNELS == 2) *wptr++ = 0;
}
data->frameIndex += framesLeft;
finished = paComplete;
} else {
for (i = 0; i < framesPerBuffer; i++) {
*wptr++ = *rptr++;
if (NUM_CHANNELS == 2) *wptr++ = *rptr++;
}
data->frameIndex += framesPerBuffer;
finished = paContinue;
}
return finished;
}
然后这是我的初始化、记录和播放功能:
PortAudio::PortAudio()
{
_err = paNoError;
PaStreamParameters baseParameters = {.channelCount = 1, .sampleFormat = PA_SAMPLE_TYPE, .hostApiSpecificStreamInfo = NULL};
init();
_inputParameters = baseParameters;
_inputParameters.device = Pa_GetDefaultInputDevice();
_inputParameters.suggestedLatency = Pa_GetDeviceInfo(_inputParameters.device)->defaultLowInputLatency;
_outputParameters = baseParameters;
_outputParameters.channelCount = 2;
_outputParameters.device = Pa_GetDefaultOutputDevice();
_outputParameters.suggestedLatency = Pa_GetDeviceInfo(_outputParameters.device)->defaultLowInputLatency;
}
int PortAudio::init()
{
int i = 0;
_data.maxFrameIndex = _totalFrames = NUM_SECONDS * SAMPLE_RATE;
_data.frameIndex = 0;
_numSamples = _totalFrames * NUM_CHANNELS;
_numBytes = _numSamples * sizeof(SAMPLE);
_data.recordedSamples = (SAMPLE *) malloc(_numBytes);
if (_data.recordedSamples == NULL) {
printf("Could not allocate record array.\n");
goto Error;
} for(i = 0; i < _numSamples; i++) _data.recordedSamples[i] = 0;
_err = Pa_Initialize();
if (_err != paNoError) goto Error;
if (_inputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default input device.\n");
goto Error;
}
return 0;
Error:
return quit();
}
paTestData PortAudio::record()
{
int i = 0;
_err = Pa_OpenStream(&_stream, &_inputParameters, NULL, SAMPLE_RATE, FRAMES_PER_BUFFER, paClipOff, recordCallback, &_data);
if (_err != paNoError) goto done;
_err = Pa_StartStream(_stream);
if (_err != paNoError) goto done;
while ((_err = Pa_IsStreamActive(_stream)) == 1)
Pa_Sleep(1000);
if (_err < 0) goto done;
_err = Pa_CloseStream(_stream);
if (_err != paNoError) goto done;
_max = 0;
_average = 0.0;
for (i = 0; i< _numSamples; i++ ) {
_val = _data.recordedSamples[i];
if (_val < 0) _val = -_val;
if (_val > _max) {
_max = _val;
}
_average += _val;
}
_average = _average / (double)_numSamples;
return _data;
done:
return _data;
}
int PortAudio::play(paTestData Audio)
{
_data.frameIndex = 0;
_data = Audio;
if (_outputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default output device.\n");
goto done;
}
_err = Pa_OpenStream(
&_stream,
NULL,
&_outputParameters,
SAMPLE_RATE,
FRAMES_PER_BUFFER,
paClipOff,
playCallback,
&_data );
if (_err != paNoError) goto done;
if (_stream) {
_err = Pa_StartStream(_stream);
if (_err != paNoError ) goto done;
while ((_err = Pa_IsStreamActive(_stream)) == 1) Pa_Sleep(100);
if (_err < 0) goto done;
_err = Pa_CloseStream(_stream);
if (_err != paNoError) goto done;
}
return 0;
done:
return quit();
}
现在我正在做的尝试传输数据是在我的主程序中:
int main(void)
{
PortAudio *audio = new PortAudio;
audio->init();
paTestData data = audio->record();
audio->play(data);
return 0;
}
一旦record()返回数据,frameIndex的值就和maxFrameIndex一样了,当运行二进制这样的时候,是记录但不播放。如果我尝试将 frameIndex 设置为任何值,它会发出可怕的嗡嗡声,我似乎无法找到这有什么问题。
我似乎找不到问题所在,但我搞砸了一些东西,最后再次切割 example 并且成功了。
我正在尝试使用 Portaudio 录制和播放一些声音,objective 是为了创建一个简单的 voip 应用程序,所以我正在尝试将录制的数据从第一个客户端传输到第二个客户端。问题是在播放录制的声音时,我要么没有播放声音,要么声音很嗡嗡声,让我解释一下:
这是我的录音和播放回调函数:
int recordCallback(const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags, void *userData)
{
paTestData *data = (paTestData*)userData;
const SAMPLE *rptr = (const SAMPLE*)inputBuffer;
SAMPLE *wptr = &data->recordedSamples[data->frameIndex * NUM_CHANNELS];
long framesToCalc;
long i;
int finished;
unsigned long framesLeft = data->maxFrameIndex - data->frameIndex;
(void) outputBuffer;
(void) timeInfo;
(void) statusFlags;
(void) userData;
if (framesLeft < framesPerBuffer) {
framesToCalc = framesLeft;
finished = paComplete;
} else {
framesToCalc = framesPerBuffer;
finished = paContinue;
} if (inputBuffer == NULL) {
for (i = 0; i<framesToCalc; i++) {
*wptr++ = SAMPLE_SILENCE;
if (NUM_CHANNELS == 2 ) *wptr++ = SAMPLE_SILENCE;
}
} else {
for(i = 0; i<framesToCalc; i++) {
*wptr++ = *rptr++;
if( NUM_CHANNELS == 2 ) *wptr++ = *rptr++;
}
}
data->frameIndex += framesToCalc;
return finished;
}
int playCallback( const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags, void *userData )
{
paTestData *data = (paTestData*)userData;
data->frameIndex = 1;
SAMPLE *rptr = &data->recordedSamples[data->frameIndex * NUM_CHANNELS];
SAMPLE *wptr = (SAMPLE*)outputBuffer;
unsigned int i = 0;
int finished;
unsigned int framesLeft = data->maxFrameIndex - data->frameIndex;
(void) inputBuffer; /* Prevent unused variable warnings. */
(void) timeInfo;
(void) statusFlags;
(void) userData;
if (framesLeft < framesPerBuffer) {
for (i = 0; i < framesLeft; i++) {
*wptr++ = *rptr++;
if (NUM_CHANNELS == 2) *wptr++ = *rptr++;
} for (; i < framesPerBuffer; i++) {
*wptr++ = 0;
if (NUM_CHANNELS == 2) *wptr++ = 0;
}
data->frameIndex += framesLeft;
finished = paComplete;
} else {
for (i = 0; i < framesPerBuffer; i++) {
*wptr++ = *rptr++;
if (NUM_CHANNELS == 2) *wptr++ = *rptr++;
}
data->frameIndex += framesPerBuffer;
finished = paContinue;
}
return finished;
}
然后这是我的初始化、记录和播放功能:
PortAudio::PortAudio()
{
_err = paNoError;
PaStreamParameters baseParameters = {.channelCount = 1, .sampleFormat = PA_SAMPLE_TYPE, .hostApiSpecificStreamInfo = NULL};
init();
_inputParameters = baseParameters;
_inputParameters.device = Pa_GetDefaultInputDevice();
_inputParameters.suggestedLatency = Pa_GetDeviceInfo(_inputParameters.device)->defaultLowInputLatency;
_outputParameters = baseParameters;
_outputParameters.channelCount = 2;
_outputParameters.device = Pa_GetDefaultOutputDevice();
_outputParameters.suggestedLatency = Pa_GetDeviceInfo(_outputParameters.device)->defaultLowInputLatency;
}
int PortAudio::init()
{
int i = 0;
_data.maxFrameIndex = _totalFrames = NUM_SECONDS * SAMPLE_RATE;
_data.frameIndex = 0;
_numSamples = _totalFrames * NUM_CHANNELS;
_numBytes = _numSamples * sizeof(SAMPLE);
_data.recordedSamples = (SAMPLE *) malloc(_numBytes);
if (_data.recordedSamples == NULL) {
printf("Could not allocate record array.\n");
goto Error;
} for(i = 0; i < _numSamples; i++) _data.recordedSamples[i] = 0;
_err = Pa_Initialize();
if (_err != paNoError) goto Error;
if (_inputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default input device.\n");
goto Error;
}
return 0;
Error:
return quit();
}
paTestData PortAudio::record()
{
int i = 0;
_err = Pa_OpenStream(&_stream, &_inputParameters, NULL, SAMPLE_RATE, FRAMES_PER_BUFFER, paClipOff, recordCallback, &_data);
if (_err != paNoError) goto done;
_err = Pa_StartStream(_stream);
if (_err != paNoError) goto done;
while ((_err = Pa_IsStreamActive(_stream)) == 1)
Pa_Sleep(1000);
if (_err < 0) goto done;
_err = Pa_CloseStream(_stream);
if (_err != paNoError) goto done;
_max = 0;
_average = 0.0;
for (i = 0; i< _numSamples; i++ ) {
_val = _data.recordedSamples[i];
if (_val < 0) _val = -_val;
if (_val > _max) {
_max = _val;
}
_average += _val;
}
_average = _average / (double)_numSamples;
return _data;
done:
return _data;
}
int PortAudio::play(paTestData Audio)
{
_data.frameIndex = 0;
_data = Audio;
if (_outputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default output device.\n");
goto done;
}
_err = Pa_OpenStream(
&_stream,
NULL,
&_outputParameters,
SAMPLE_RATE,
FRAMES_PER_BUFFER,
paClipOff,
playCallback,
&_data );
if (_err != paNoError) goto done;
if (_stream) {
_err = Pa_StartStream(_stream);
if (_err != paNoError ) goto done;
while ((_err = Pa_IsStreamActive(_stream)) == 1) Pa_Sleep(100);
if (_err < 0) goto done;
_err = Pa_CloseStream(_stream);
if (_err != paNoError) goto done;
}
return 0;
done:
return quit();
}
现在我正在做的尝试传输数据是在我的主程序中:
int main(void)
{
PortAudio *audio = new PortAudio;
audio->init();
paTestData data = audio->record();
audio->play(data);
return 0;
}
一旦record()返回数据,frameIndex的值就和maxFrameIndex一样了,当运行二进制这样的时候,是记录但不播放。如果我尝试将 frameIndex 设置为任何值,它会发出可怕的嗡嗡声,我似乎无法找到这有什么问题。
我似乎找不到问题所在,但我搞砸了一些东西,最后再次切割 example 并且成功了。