首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么这种双缓冲方案每次从磁盘读取音频文件时都会产生可听到的点击?

为什么这种双缓冲方案每次从磁盘读取音频文件时都会产生可听到的点击?
EN

Stack Overflow用户
提问于 2020-09-12 05:15:34
回答 1查看 51关注 0票数 0

下面的双缓冲方案似乎对我来说是可行的,但出于某种原因,每次循环在顶部再次启动时,都会有一个可听到的点击声。

下面是一个可以使用的测试wav文件:https://github.com/JoshuaD84/jwaveform/blob/master/test4.wav,但是这个bug并不是特定于任何一个测试文件。

代码语言:javascript
运行
复制
#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将其编译为一个文件)。

备注:

  1. 我已经检查了文件,它在0开始和结束,所以剪辑不是由音频的形状造成的。
  2. 如果我从文件的最后一个缓冲区的末尾剪掉100字节,我就得不到剪辑。
  3. 如果我读取标头subChunkSize字段,不管文件是什么,它报告的数据字段比我所能读取的要大312个字节。
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-09-14 01:32:16

问题不在于双缓冲方案;这很好。

问题是您假设音频文件的其余部分是有效的音频数据,但是在该文件的末尾有垃圾数据经过音频数据。当你播放那些垃圾数据时,听起来就像一次点击。

为了避免单击,只读取Subchunk2Size中指定的字节和wav格式中指定的字节。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63857060

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档