【问题标题】:how to make audio playback smooth using waveOutWrite()如何使用 waveOutWrite() 使音频播放流畅
【发布时间】:2012-03-22 05:09:55
【问题描述】:

我在尝试使用 waveOutWrite() 实现流畅的音频播放时遇到问题。我的数据包括许多从相机获取的 adpcmdata 块,在解码每个 adpcm 块后,我使用 waveOutWrite() 播放它。第一个块已成功播放(至少我能听到),但是当我播放下一个块时这些块之间存在间隙时我遇到了问题。我尝试在使用 waveOutWrite() 后调用 sleep() ,但它不行。任何人都可以告诉我在这种情况下我如何变得顺利?我播放音频的方式有什么问题吗?

for (i = 0, i < MaxBlockData, i++)  


        BYTE * pcmBuff = new BYTE[length*8];
        memset(pcmBuff, 0, length*8);
        G726 g726;

        int pcmDataSize = 0;
        g726.SetRate(g726.Rate32kBits);
        g726.SetLaw(g726.PCM16);
        pcmDataSize = g726.Decode(pcmBuff, adpcmData[i], 0, length*8); /decode adcmData PCM 16

        if(pcmDataSize > 0)
        {
            int sampleRate = 8000;
            CHAR* waveIn = new CHAR[pcmDataSize];

            HWAVEIN hWaveIn;
            WAVEHDR WaveInHdr;
            MMRESULT result;
            HWAVEOUT hWaveOut;

            WAVEFORMATEX pFormat;
            pFormat.wFormatTag = WAVE_FORMAT_PCM;
            pFormat.nChannels = 1;
            pFormat.nSamplesPerSec = sampleRate;
            pFormat.nAvgBytesPerSec = 2 * sampleRate;
            pFormat.nBlockAlign = 2;
            pFormat.wBitsPerSample = 16;
            pFormat.cbSize = 0;

            result = waveInOpen(&hWaveIn, WAVE_MAPPER, &pFormat, 0, 0, WAVE_FORMAT_DIRECT);

            if(result != MMSYSERR_NOERROR)
            {
                char fault[256];
                waveInGetErrorTextA(result, fault, 256);
                MessageBoxA(NULL, fault, "Failed to open waveform input device.", MB_OK | MB_ICONEXCLAMATION);
                return;
            }

            WaveInHdr.lpData = (LPSTR)waveIn;
            WaveInHdr.dwBufferLength = pcmDataSize;
            WaveInHdr.dwBytesRecorded = 0;
            WaveInHdr.dwUser = 0;
            WaveInHdr.dwFlags = 0;
            WaveInHdr.dwLoops = 0;

            waveInPrepareHeader(hWaveIn, &WaveInHdr, sizeof(WAVEHDR));
            memcpy(WaveInHdr.lpData, pcmBuff, pcmDataSize);

            if(waveOutOpen(&hWaveOut, WAVE_MAPPER, &pFormat, 0, 0, WAVE_FORMAT_DIRECT))
            {
                MessageBoxA(NULL, "Failed to replay", NULL, MB_OK | MB_ICONEXCLAMATION );
            }

            waveOutWrite(hWaveOut, &WaveInHdr, sizeof(WaveInHdr)); 
            Sleep((pcmDataSize/sampleRate ) * 1000); //Sleep for as long as there was recorded

            waveOutUnprepareHeader(hWaveOut, &WaveInHdr, sizeof(WAVEHDR));
            waveInUnprepareHeader(hWaveIn, &WaveInHdr, sizeof(WAVEHDR));
            waveInClose(hWaveIn);
            waveOutClose(hWaveOut);


            WaveInHdr.lpData = NULL;
            delete []waveIn;
        }
    }

感谢您阅读我的问题。

【问题讨论】:

  • 我已经回答了一个类似的问题,所以我将把它添加为评论。要消除音频块之间的延迟,您需要实现double buffering。那里有一个很好的链接,其中包含 WaveOutXXX 函数的教程。这是original answer的链接。

标签: c++ audio-streaming ip-camera


【解决方案1】:

要使用 waveOut* 系列顺利播放音频,您需要打开设备,分配缓冲区并继续向设备发送缓冲区,以保持积压的数据播放。在您的代码中 Sleep 的位置,您应该致力于准备新数据并将其写入设备,同时检查播放的缓冲区(WHDR_DONE 标志设置为指示驱动程序不再使用缓冲区和应用程序接收它)。

【讨论】:

    【解决方案2】:

    我不会这样工作的。
    当你播放第一个样本时,你不能在下一个样本的时候睡觉,而是应该使用双缓冲或多缓冲和回调机制。
    整体协议如下:
    1) 从相机或其他任何地方获取第一个块
    2) 从相机或其他任何地方获取第二个块
    3) 写入第一个块,然后写入第二个块,无需等待。
    然后创建一个循环,等待来自回调的信号,并在收到信号后写入下一个捕获的块。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-11-22
      • 2023-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-20
      • 1970-01-01
      相关资源
      最近更新 更多