Windows和Linux下的系统声音控制

本文介绍了一种在Windows和Linux平台上实现系统音量控制的方法,包括获取和设置音量及静音状态。针对不同操作系统提供了具体的C++实现方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简介

项目中需要在windows和linux系统下对系统的声音进行控制,相关操作包括获取系统的音量,设置系统的音量,获取系统的静音状态和静音,特此记录相关的C++实现。

主要涉及的系统有windows和ubuntu系统。

实现

  • windows

    windows下使用WASAPI来获取设置音量。

  • linux

    在linux上使用amixer的文本方式控制音量。alsamixer是Linux 音频架构ALSA中的Alsa工具的其中一个,用于配置音频的各个参数。

    amixer,是alsamixer的文本模式,即命令行模式,需要用amixer命令的形式去配置你的声卡的各个选项。

    • 其帮助文档相关参数如下:

      在这里插入图片描述

    • 使用到的相关设置:

      # 获取声音状态
      # -D 指定声音脉冲
      # sget 获取主通道Master状态
      # awk '/%/{print $5,$6}' OFS=","       查找含有%号的字符行,并以逗号格式化输出音量和是否静音
      # uniq 去重
      # tr -d [/] 删除多余的括号
      amixer -D pulse sget "Master" | awk '/%/{print $5,$6}' OFS="," | uniq | tr -d '['/']'
      
      # 设置系统音量为10%
      amixer -D pulse sset "Master" 10%
      
      # 设置系统音量静音,取消静音为:unmute
      amixer -D pulse sset "Master" mute
      

相关代码实现了windows和linux的相关声音控制,代码已测试可用。

  • 工具库头文件

    #include "utility.h"
    
    #include <iostream>
    
    int main()
    {
        int iVolume = 0;
        bool mute = false;
    
        // 获取系统声音信息
        Utility::getSysSoundInfo(iVolume, mute);
        std::cout << "volume:" << iVolume << ",mute:" << mute << std::endl;
    
        // 设置音量
        std::cout << "set the volume(0-100):" << std::endl;
        std::cin >> iVolume;
        Utility::setSysVolume(iVolume);
    
        // 设置静音
        int tmpMut = 1;
        std::cout << "set the mute(1:mute,0:unmute):" << std::endl;
        std::cin >> tmpMut;
        Utility::setSysMutex(tmpMut == 1);
    
        // 再次获取系统声音信息
        iVolume = 0;
        mute = false;
        Utility::getSysSoundInfo(iVolume, mute);
        std::cout << "volume:" << iVolume << ",mute:" << mute << std::endl;
    
        return 0;
    }
    
    
  • 工具库实现文件

    #include "utility.h"
    
    #ifdef WIN32
    #include <windows.h>
    #include <mmdeviceapi.h>
    #include <endpointvolume.h>
    #include <Audioclient.h>
    
    #pragma comment(lib, "Ole32.lib")
    #endif
    
    Utility::Utility()
    {
    
    }
    
    std::vector<std::string> Utility::splitStr(const std::string &str, const std::string &delim)
    {
        std::vector<std::string> vec;
        try
        {
            std::regex regex(delim);
    
            return std::vector<std::string>{
                std::sregex_token_iterator(str.begin(), str.end(), regex, -1), std::sregex_token_iterator()
            };
        }
        catch(const std::exception &e)
        {
            return std::vector<std::string>();
        }
    }
    
    bool Utility::getSysSoundInfo(int &ivolume, bool &mute)
    {
    #ifdef WIN32
        return getWindowsSoundInfo(ivolume, mute);
    #else
        return getLinuxSoundInfo(ivolume, mute);
    #endif
    }
    
    bool Utility::setSysVolume(int iVolume)
    {
    #ifdef WIN32
        return setWindowsVolume(iVolume);
    #else
        return Utility::setLinuxVolume(iVolume);
    #endif
    }
    
    bool Utility::setSysMutex(bool mute)
    {
    #ifdef WIN32
        return setWindowsMutex(mute);
    #else
        return Utility::setLinuxMutex(mute);
    #endif
    }
    
    std::string Utility::exeCmd(const std::string &cmd)
    {
        FILE* fp = popen(cmd.data(), "r");
        if (fp == nullptr)
        {
            return "";
        }
    
        std::string result;
        char buf[1024] = {0};
        while (fgets(buf, sizeof(buf), fp))
        {
            result +=  buf;
        }
    
        pclose(fp);
    
        auto size = result.size();
        if (size > 0 && result[size - 0] == '\n')
        {
            result = result.substr(0, size -1);
        }
    
        return result;
    }
    
    #ifdef WIN32
    bool Utility::getWindowsSoundInfo(int &iVolume, bool &mute)
    {
        CoInitialize(nullptr);
    
        HRESULT hr;
        bool result = false;
    
        IMMDeviceEnumerator* pDeviceEnum = nullptr;
        IMMDevice* pDevice = nullptr;
        IAudioEndpointVolume* pAudioVolume = nullptr;
    
        hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (VOID **)&pDeviceEnum);
        if (FAILED(hr))
        {
            goto exit;
        }
    
        hr = pDeviceEnum->GetDefaultAudioEndpoint(eRender, eMultimedia, &pDevice);
        if (FAILED(hr))
        {
            goto exit;
        }
    
        hr = pDevice->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_ALL, nullptr, (void **)&pAudioVolume);
        if (FAILED(hr))
        {
            goto exit;
        }
    
        // 音量
        float tmpVolume;
        pAudioVolume->GetMasterVolumeLevelScalar(&tmpVolume);
    
        iVolume = (int)(tmpVolume * 100);
    
        // 是否静音
        BOOL tmpMute;
        pAudioVolume->GetMute(&tmpMute);
    
        mute = tmpMute;
    
        result = true;
    
    exit:
        if (pAudioVolume != nullptr)
        {
            pAudioVolume->Release();
        }
    
        if (pDevice != nullptr)
        {
            pDevice->Release();
        }
    
        if (pDeviceEnum != nullptr)
        {
            pDeviceEnum->Release();
        }
    
        CoUninitialize();
    
        return result;
    }
    
    bool Utility::setWindowsVolume(int iVolume)
    {
        CoInitialize(nullptr);
    
        float tmpVolume = iVolume / 100.0f;
        HRESULT hr;
        bool result = false;
    
        IMMDeviceEnumerator* pDeviceEnum = nullptr;
        IMMDevice* pDevice = nullptr;
        IAudioEndpointVolume* pAudioVolume = nullptr;
    
        hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (VOID **)&pDeviceEnum);
        if (FAILED(hr))
        {
            goto exit;
        }
    
        hr = pDeviceEnum->GetDefaultAudioEndpoint(eRender, eMultimedia, &pDevice);
        if (FAILED(hr))
        {
            goto exit;
        }
    
        hr = pDevice->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_ALL, nullptr, (void **)&pAudioVolume);
        if (FAILED(hr))
        {
            goto exit;
        }
    
        // 设置音量
        pAudioVolume->SetMasterVolumeLevelScalar(tmpVolume, &GUID_NULL);
    
        result = true;
    
    exit:
        if (pAudioVolume != nullptr)
        {
            pAudioVolume->Release();
        }
    
        if (pDevice != nullptr)
        {
            pDevice->Release();
        }
    
        if (pDeviceEnum != nullptr)
        {
            pDeviceEnum->Release();
        }
    
        CoUninitialize();
    
        return result;
    }
    
    bool Utility::setWindowsMutex(bool mute)
    {
        CoInitialize(nullptr);
    
        HRESULT hr;
        bool result = false;
    
        IMMDeviceEnumerator* pDeviceEnum = nullptr;
        IMMDevice* pDevice = nullptr;
        IAudioEndpointVolume* pAudioVolume = nullptr;
    
        hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (VOID **)&pDeviceEnum);
        if (FAILED(hr))
        {
            goto exit;
        }
    
        hr = pDeviceEnum->GetDefaultAudioEndpoint(eRender, eMultimedia, &pDevice);
        if (FAILED(hr))
        {
            goto exit;
        }
    
        hr = pDevice->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_ALL, nullptr, (void **)&pAudioVolume);
        if (FAILED(hr))
        {
            goto exit;
        }
    
        // 设置音量
        pAudioVolume->SetMute(mute, &GUID_NULL);
    
        result = true;
    
    exit:
        if (pAudioVolume != nullptr)
        {
            pAudioVolume->Release();
        }
    
        if (pDevice != nullptr)
        {
            pDevice->Release();
        }
    
        if (pDeviceEnum != nullptr)
        {
            pDeviceEnum->Release();
        }
    
        CoUninitialize();
    
        return result;
    }
    #else
    bool Utility::getLinuxSoundInfo(int &iVolume, bool &mute)
    {
        std::string cmd = "amixer -D pulse sget \"Master\" | awk '/%/{print $5,$6}' OFS=\",\" | uniq | tr -d '['/']'/'\n'";
    
        auto result = Utility::exeCmd(cmd);
    
        auto vec = Utility::splitStr(result, ",");
        if (vec.size() >= 2)
        {
            iVolume = std::stoi(vec[0]);
    
            mute = (vec[1] == "off");
    
            return true;
        }
        else
        {
            return false;
        }
    }
    
    bool Utility::setLinuxVolume(int iVolume)
    {
        std::string cmd = std::string("amixer -D pulse sset \"Master\" ") + std::to_string(iVolume) + "%";
    
        Utility::exeCmd(cmd);
    
        return true;
    }
    
    bool Utility::setLinuxMutex(bool mute)
    {
        auto cmd = std::string("amixer -D pulse sset \"Master\" ") + (mute ? "mute" : "unmute");
    
        Utility::exeCmd(cmd);
    
        return true;
    }
    #endif
    
    
  • 测试代码

    #include "utility.h"
    
    #include <iostream>
    
    int main()
    {
        int iVolume = 0;
        bool mute = false;
    
        // 获取系统声音信息
        Utility::getSysSoundInfo(iVolume, mute);
        std::cout << "volume:" << iVolume << ",mute:" << mute << std::endl;
    
        // 设置音量
        std::cout << "set the volume(0-100):" << std::endl;
        std::cin >> iVolume;
        Utility::setSysVolume(iVolume);
    
        // 设置静音
        int tmpMut = 1;
        std::cout << "set the mute(1:mute,0:unmute):" << std::endl;
        std::cin >> tmpMut;
        Utility::setSysMutex(tmpMut == 1);
    
        // 再次获取系统声音信息
        iVolume = 0;
        mute = false;
        Utility::getSysSoundInfo(iVolume, mute);
        std::cout << "volume:" << iVolume << ",mute:" << mute << std::endl;
    
        return 0;
    }
    
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xiaobaiPlayGame

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值