声音未正确播放,嗡嗡声而不是录制的声音 - Portaudio

Posted

技术标签:

【中文标题】声音未正确播放,嗡嗡声而不是录制的声音 - Portaudio【英文标题】:Sound not properly played, buzzing sound instead of recorded sound - Portaudio 【发布时间】:2021-11-28 13:43:28 【问题描述】:

我正在尝试使用 Portaudio 录制和播放一些声音,目的是创建一个简单的 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 设置为任何值,它会发出可怕的嗡嗡声,我似乎找不到问题所在。

【问题讨论】:

【参考方案1】:

我似乎找不到哪里出了问题,但我搞砸了一些东西,最后又剪掉了example,它起作用了。

【讨论】:

以上是关于声音未正确播放,嗡嗡声而不是录制的声音 - Portaudio的主要内容,如果未能解决你的问题,请参考以下文章

如何在 UILocalNotification 中播放录制的声音

我的电脑突然放歌放电影没声音,显示音频设备无法播放,请检查声卡设置

是否可以录制声卡上播放的声音?

如何在 Android 上生成复杂的声音?

是否可以从一个窗口录制声音?

播放系统录制的声音