下面的双缓冲方案似乎对我来说是可行的,但出于某种原因,每次循环在顶部再次启动时,都会有一个可听到的点击声。
下面是一个可以使用的测试wav文件:https://github.com/JoshuaD84/jwaveform/blob/master/test4.wav,但是这个bug并不是特定于任何一个测试文件。
#include <windows.h>
#include <mmsystem.h>
#include <iostream>
#include <fstream>
#include <bitset>
#pragma comment(lib, "winmm.lib")
HWAVEOUT hWaveOut = 0;
WAVEFORMATEX wfx;
int main() {
  wfx = { WAVE_FORMAT_PCM, 2, 44100, 176400, 4, 16, 0 };
  waveOutOpen(&hWaveOut, WAVE_MAPPER, &wfx, 0, 0, CALLBACK_NULL);
  
  const int increment = 80000;
  WAVEHDR* oldHeader = nullptr;
  for (int k = 0; k < 50; k++) {
    std::ifstream inStream;
    inStream.open("test4.wav", std::ios::in | std::ios::binary);
    char headerInfo[44]; //get past the wav header to the audio data
    inStream.read(headerInfo, 44);
    while (true) {
      char* buffer = new char[increment];
      inStream.read(buffer, increment);
      DWORD bytesRead = inStream.gcount();
      if (bytesRead <= 0) {
        break;
      } 
      WAVEHDR* header = new WAVEHDR{ buffer, bytesRead, 0, 0, 0, 0, 0, 0 };
      waveOutPrepareHeader(hWaveOut, header, sizeof(WAVEHDR));
      waveOutWrite(hWaveOut, header, sizeof(WAVEHDR));
      if (oldHeader != nullptr) {
        while (!(oldHeader->dwFlags & WHDR_DONE)) {
          Sleep(1);
        }
        waveOutUnprepareHeader(hWaveOut, oldHeader, sizeof(oldHeader));
        delete[] oldHeader->lpData;
        delete oldHeader;
      }
      oldHeader = header;
    }
  }
}我肯定这是件愚蠢的事情,但我已经对它做了两个晚上的修补,我不知道我在哪里犯了这个错误。
(为了您的方便:我可以在64位VS developer命令提示符下使用命令cl /EHsc test.cpp将其编译为一个文件)。
备注:
subChunkSize字段,不管文件是什么,它报告的数据字段比我所能读取的要大312个字节。发布于 2020-09-14 01:32:16
问题不在于双缓冲方案;这很好。
问题是您假设音频文件的其余部分是有效的音频数据,但是在该文件的末尾有垃圾数据经过音频数据。当你播放那些垃圾数据时,听起来就像一次点击。
为了避免单击,只读取Subchunk2Size中指定的字节和wav格式中指定的字节。
https://stackoverflow.com/questions/63857060
复制相似问题