Win32 PlaySound:如何控制音量?

2024-01-08

我正在使用 Win32 多媒体函数播放声音 http://msdn.microsoft.com/en-us/library/dd743680%28VS.85%29.aspx从我的应用程序中播放声音。

我希望能够动态调整正在播放的声音的音量without修改系统音量。

我能找到的关于操纵播放声音音量的唯​​一建议播放声音 http://msdn.microsoft.com/en-us/library/dd743680%28VS.85%29.aspx是要使用波形输出设定音量 http://msdn.microsoft.com/en-us/library/dd743874%28VS.85%29.aspx,但是该函数设置系统范围的音量级别(不是我想要的)。


两种可能的解决方案:

首先,如果您的目标是 Vista 及更高版本,则可以使用新的 Windows 音频 API 来调整每个应用程序的音量。 ISimpleAudioVolume、IAudioEndpointVolume 等...

如果不合适,可以将 WAV 文件直接加载到内存中并就地修改样本。尝试这个:

将 WAV 文件从磁盘读取到内存缓冲区中,然后按比例缩小样本。我假设所讨论的 WAV 文件是带有未压缩 (PCM) 样本的 16 位立体声。立体声或单声道。如果不是,那么大部分内容都会被抛之脑后。

我将把 WAV 文件字节读取到内存中作为读者的练习:但是让我们从以下代码开始,其中“ReadWavFileIntoMemory”是您自己的函数。

DWORD dwFileSize;
BYTE* pFileBytes;
ReadWavFileIntoMemory(szFilename, &pFileBytes, &dwFileSize);

此时,对 pFileBytes 的检查将如下所示:

RIFF....WAVEfmt ............data....

这是 WAV 文件头。 “data”是音频样本块的开始。

查找“数据”部分,并将“数据”后面的 4 个字节读入 DWORD。这是包含音频样本的“数据”块的大小。样本数(假设 PCM 16 位是该数字除以 2)。

// FindDataChunk is your function that parses the WAV file and returns the pointer to the "data" chunk.
BYTE* pDataOffset = FindDataChunk(pBuffer);
DWORD dwNumSampleBytes = *(DWORD*)(pDataOffset + 4);
DWORD dwNumSamples = dwNumSamplesBytes / 2;

现在,我们将创建一个样本指针,指向内存缓冲区中的第一个真实样本:

SHORT* pSample = (SHORT*)(pDataOffset + 8);

pSample 指向 WAV 文件中的第一个 16 位样本。因此,我们准备将音频样本缩放到适当的音量级别。假设我们的音量范围在 0.0 到 1.0 之间。其中 0.0 表示完全沉默。 1.0是正常的全音量。现在我们只需将每个样本乘以目标体积:

float fVolume = 0.5; // half-volume
for (DWORD dwIndex = 0; dwIndex < dwNumSamples; dwIndex++)
{
    SHORT shSample = *pSample;
    shSample = (SHORT)(shSample * fVolume);
    *pSample = shSample;
    pSample++;


    if (((BYTE*)pSample) >= (pFileBytes + dwFileSize - 1))
       break;
}

此时,您已准备好使用 PlaySound 播放内存中的 WAV 文件:

PlaySound((LPCSTR)pFileBytes, NULL, SND_MEMORY);

那应该可以了。如果您打算使用 SND_ASYNC 标志使上述调用成为非阻塞,那么在播放完成之前您将无法释放内存缓冲区。所以要小心。

至于WAV文件头的解析。我通过声明一个名为“FindDataChunk”的假设函数来摆脱这个困境。您可能应该投资编写一个合适的 WAV 文件头解析器,而不是仅仅寻找头中第一次遇到“数据”的位置。为了简洁起见,我省略了通常的错误检查。因此,上述代码可能需要解决一些安全问题 - 特别是当它涉及遍历内存缓冲区并写入其中时。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Win32 PlaySound:如何控制音量? 的相关文章

  • 如何使用MemoryCache代替Timer来触发一个方法?

    以下方法通过等待已运行操作的结果来处理并发请求 对数据的请求可能会使用相同 不同的凭据同时出现 对于每组唯一的凭据 最多可以有一个GetCurrentInternal呼叫正在进行中 当准备就绪时 该呼叫的结果将返回给所有排队的服务员 pri
  • 如何读取扩展文件属性/文件元数据

    因此 我按照教程使用 ASP net core 将文件 上传 到本地路径 这是代码 public IActionResult About IList
  • 如何在 C# 中从 UNIX 纪元时间转换并考虑夏令时?

    我有一个从 unix 纪元时间转换为 NET DateTime 值的函数 public static DateTime FromUnixEpochTime double unixTime DateTime d new DateTime 19
  • 推导指南中的引用和值之间的差异

    考虑类型A template
  • 使用 ffmpeg 在一个音频文件中实现多个淡入/淡出效果

    我在向一个音频文件添加多种淡入淡出效果时遇到一些问题 当我尝试使用这样的命令时 ffmpeg y i home user video test sound mp3 af afade t in ss 0 d 3 afade t out st
  • 互斥体实现可以互换(独立于线程实现)

    所有互斥体实现最终都会调用相同的基本系统 硬件调用吗 这意味着它们可以互换吗 具体来说 如果我使用 gnu parallel算法 使用openmp 并且我想让他们称之为线程安全的类我可以使用boost mutex用于锁定 或者我必须编写自己
  • 单元测试一起运行时失败,单独运行时通过

    所以我的单元测试遇到了一些问题 我不能只是将它们复制并粘贴到这里 但我会尽力而为 问题似乎是 如果我一项一项地运行测试 一切都会按预期进行 但如果我告诉它一起运行测试 则 1 5 将通过 TestMethod public void Obj
  • 读取文件特定行号的有效方法。 (奖励:Python 手册印刷错误)

    我有一个 100 GB 的文本文件 它是来自数据库的 BCP 转储 当我尝试导入它时BULK INSERT 我在第 219506324 行上收到一个神秘错误 在解决此问题之前 我想看看这一行 但可惜的是我最喜欢的方法 import line
  • 如何从 .resx 文件条目获取注释

    资源文件中的字符串有名称 值和注释 The ResXResourceReader类让我可以访问名称和值 有办法看评论吗 你应该能够得到Comment via ResXDataNode class http msdn microsoft co
  • 如何为 Python 中的应用程序设置专用屏幕区域?

    MS OneNote 就是一个很好的例子 它可以选择固定在屏幕的一侧 并将所有其他窗口推到一侧 当最大化或调整其他窗口大小时 它们只能扩展到 OneNote 的边缘 Python 使用 Tkinter 或其他模块是否具有此功能 感谢您的帮助
  • ASP.NET:获取自 1970 年 1 月 1 日以来的毫秒数

    我有一个 ASP NET VB NET 日期 我试图获取自 1970 年 1 月 1 日以来的毫秒数 我尝试在 MSDN 中寻找方法 但找不到任何东西 有谁知道如何做到这一点 从 NET 4 6 开始 该方法ToUnixTimeMillis
  • 如何在 Linq 中获得左外连接?

    我的数据库中有两个表 如下所示 顾客 C ID city 1 Dhaka 2 New york 3 London 个人信息 P ID C ID Field value 1 1 First Name Nasir 2 1 Last Name U
  • 将 Excel 导入到 Datagridview

    我使用此代码打开 Excel 文件并将其保存在 DataGridView 中 string name Items string constr Provider Microsoft Jet OLEDB 4 0 Data Source Dial
  • 上下文敏感与歧义

    我对上下文敏感性和歧义如何相互影响感到困惑 我认为正确的是 歧义 歧义语法会导致使用左推导或右推导构建多个解析树 所有可能的语法都是二义性的语言是二义性语言 例如 C 是一种不明确的语言 因为 x y 总是可以表示两个不同的事物 如下所述
  • HttpWebRequest 在第二次调用时超时

    为什么以下代码在第二次 及后续 运行时超时 代码挂在 using Stream objStream request GetResponse GetResponseStream 然后引发 WebException 表示请求已超时 我已经尝试过
  • 英特尔 Pin 与 C++14

    问题 我有一些关于在 C 14 或其他 C 版本中使用英特尔 Pin 的问题 使用较新版本从较旧的 C 编译代码很少会出现任何问题 但由于 Intel Pin 是操作指令级别的 如果我使用 C 11 或 C 14 编译它 是否会出现任何不良
  • 防止在工厂方法之外实例化对象

    假设我有一个带有工厂方法的类 class A public static A newA Some code logging return new A 是否可以使用 a 来阻止此类对象的实例化new 那么工厂方法是创建对象实例的唯一方法吗 当
  • 如何使用 Word Automation 获取页面范围

    如何使用办公自动化找到 Microsoft Word 中第 n 页的范围 似乎没有 getPageRange n 函数 并且不清楚它们是如何划分的 这就是您从 VBA 执行此操作的方法 转换为 Matlab COM 调用应该相当简单 Pub
  • 在客户端系统中安装后桌面应用程序无法打开

    我目前正在使用 Visual Studio 2017 和 4 6 1 net 框架 我为桌面应用程序创建了安装文件 安装程序在我的系统中完美安装并运行 问题是安装程序在其他计算机上成功安装 但应用程序无法打开 edit 在客户端系统中下载了
  • 如何正确使用 std::condition_variable?

    我很困惑conditions variables以及如何 安全 使用它们 在我的应用程序中 我有一个创建 gui 线程的类 但是当 gui 是由 gui 线程构造时 主线程需要等待 情况与下面的函数相同 主线程创建互斥体 锁和conditi

随机推荐