开发者

C++使用alsa库实现播放声音文件

目录
  • 前言
  • 一、命令行
    • 1.ffmpeg
    • 2.aplay
  • 二、代码实现
    • 三、知识补充

      前言

      平常读麦克风的场景居多,有时候也需要播放一个声音文件,这里就介绍怎么处理。

      一、命令行

      1.ffmpeg

      ffmpeg -i <filename.wav> -f alsa default

      2.aplay

      aplay -i <filename.wav>

      如果提示找不到aplay就安装工具:

      sudo apt install alsa-utils

      二、代码实现

      main.cpp

      #include <alsa/asoundlib.h>
      #include <IOStream>
      #include <fstream>
      
      #define PCM_DEVICE "default"//默认的播放设备,你可以在settings里面调换
      
      int main(int argc, char *argv[]) {
          const char *audioFilename = "../wakeup.wav";
      
          // 配置ALSA参数
          snd_pcm_t *pcmHandle;
          if (snd_pcm_open(&pcmHandle, PCM_DEVICE, SND_PCM_STREAM_PLAYBACK, 0) < 0) {
              std::cerr << "Error: Failed to open PCM device" << std::endl;
              return 1;
          }
      
          snd_pcm_hw_params_t *params;
          snd_pcm_hw_params_alloca(&params);
          snd_pcm_hw_params_any(pcmHandle, params);
          snd_pcm_hw_params_set_Access(pcmHandle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
          snd_pcm_hw_params_set_format(pcmHandle, params, SND_PCM_FORMAT_S16_LE);
          snd_pcm_hw_params_set_channels(pcmHandle, params, 2);
          unsigned int sampleRate = 48000;
          snd_pcm_hw_params_set_rate_near(pcmHandle, params, &sampleRate, nullptr);
          snd_pcm_uframes_t bufferSize = 512;
          snd_pcm_hw_params_set_buffer_size_near(pcmHandle, params, &bufferSize);
          snd_pcm_hw_params(pcmHandle, params);
      
          std::ifstream ifs("../wakeup.wav");
          if (ifs.is_open()) {
              std::string data;
              size_t size;
              char buffer[8192];
              while ((size = ifs.readsome(buffer, 8192)) > 0) {
                  data.append(buffer, size);
              }
          编程客栈    snd_pcm_sframes_t err = snd_pcm_writei(pcmHandle, (const void *) data.c_str(),
                                                     data.size()); 
              if (err < 0) {
                  std::cerr << "Error: Failed to write PCM device" << std::endl;
              }
              ifs.close();
          }
      
          // 关闭PCM设备和文件
          snd_pcm_close(pcmHandle);
          return 0;
      }

      CMakeLists.txt

      cmake_minimum_required(VERSION 3.10)

      project(write_speaker)

      set(CMAKE_CXX_STANDARD 11)

      add_executable(${PROJECT_NAME} main.cpp)

      target_link_libraries(${PROJECT_NAME} asound)

      三、知识补充

      C++使用Alsa采集linux音频

      1、运行时前先装库,sudo apt-get install libalsa

      2遍tab自动提示出库文件,选择库,alsa-ocaml-dev,最终的命令行为:sudo apt-get install libalsa-ocaml-dev

      2、编译执行脚本,gcc -o main main.c -lasound;

      3、执行 ./main

      以下是代码

      #include <stdlib.h>
      #include <stdio.h>
      #include <alsa/asoundlib.h>
      #include <signal.h>
      static int recording;
      
      void stop_record(int param)
      {
      recording = 0;
      }
      void InitCapture(snd_pcm_t ** handle,snd_pcm_hw_params_t ** params,snd_pcm_uframes_t* frames,char ** buffer,int* size)
      {
      int ret;
      unsigned int val;
      int dir;
      //打开设备
      ret = snd_pcm_open(handle, “default”, SND_PCM_STREAM_CAPTURE, 0);
      printf(“after open file\n”);
      if (ret < 0)
      {
      fprinwww.devze.comtf(stderr, “unable to open device:%s\n”, snd_strerror(ret));
      exit(1);
      }
      //分配一个硬件参数结构体
      snd_pcm_hw_params_alloca(params);
      
      //使用默认参数
      snd_pcm_hw_params_any(*handle, *params);
      
      //翻译
          snd_pcm_hw_params_set_access(*handle, *params, SND_PCM_ACCESS_RW_INTERLEAVED);
      
      //S16小端
      snd_pcm_hw_params_set_format(*handle, *params, SND_PCM_FORMAT_S16_LE);
      
      //双通道,立体声
      snd_pcm_hw_params_set_channels(*handle, *params, 2);
      
      //采样率
      val = 44100;
      snd_pcm_hw_params_set_rate_near(*handle, *params,&val,&dir);
      
      *frames = 32;
      snd_pcm_hw_params_set_period_size_near(*handle, *params,frames,&dir);
      
      //参数生效
      ret = snd_pcm_hw_params(*handle, *params);
      if (ret<0)
      {
      	www.devze.comfprintf(stderr, "unable to set hw parameters:%s\n", snd_strerror(ret));
      		exit(1);
      }
      //得到一个周期的数据大小
      snd_pcm_hw_paramhttp://www.devze.coms_get_period_size(*params, frames, &dir);
      
      //16位双通道,16位为2字节,2字节*2通道=4,假如frames=1024,则size是1024*4 = 4096
      *size = *frames * 4;
      *buffer = (char*)malloc(*size); 
      
      //设置一个周期的时间长度
      snd_pcm_hw_params_get_period_time(*params, &val, &dir);
      }
      
      void CaptureAudio(snd_pcm_t ** handle,snjsd_pcm_uframes_t* frames,char ** buffer,int* size,FILE ** pFile)
      {
      int ret;
      
      recording = 1;
      while (recording)
      {
      	ret = snd_pcm_readi(*handle, *buffer,*frames);
      	if (ret == -EPIPE )
      	{
      		fprintf(stderr, "overrun occurred\n");
      		snd_pcm_prepare(*handle);
      	}
      	else if (ret < 0)
      	{
      		fprintf(stderr, "error from read\n");
      		snd_strerror(ret);
      	}
      	else if (ret != (int)(*frames))
      	{
      		fprintf(stderr, "short read %d frames\n",ret);
      	}
      	printf("write to file......%d\n", *size);
      	//写到标准输出中去
      	ret = fwrite(*buffer, sizeof(char), *size, *pFile);
      	if (ret != *size)
      	{
      		fprintf(stderr, "short write :write %d bytes\n", ret);
      	}
      	if (signal(SIGINT, stop_record)==SIG_ERR)
      	{
      		fprintf(stderr, "signal failed\n");
      	}
      }
      }
      
      void CloseCaptureDevice(FILE ** pFile,snd_pcm_t ** handle,char ** buffer)
      {
      printf(“write file exit\n”);
      snd_pcm_drain(*handle);
      snd_pcm_close(*handle);
      free(*buffer);
      fclose(*pFile);
      }
      
      int main()
      {
      FILE * pFile;
      pFile = fopen(“test.pcm”, “wb”);
      int size;
      //给文件操作分配一个句柄
      snd_pcm_t * handle;
      //硬件参数
      snd_pcm_hw_params_t * params;
      //
      snd_pcm_uframes_t frames;
      char * buffer;
      printf(“before open file\n”);
      InitCapture(&handle,&params,&frames,&buffer,&size);
      CaptureAudio(&handle,&frames,&buffer,&size,&pFile);
      CloseCaptureDevice(&pFile,&handle,&buffer);
      printf(“write file exit\n”);
      
      return 0;
      }

      到此这篇关于C++使用alsa库实现播放声音文件的文章就介绍到这了,更多相关C++ alsa播放声音文件内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!

      0

      上一篇:

      下一篇:

      精彩评论

      暂无评论...
      验证码 换一张
      取 消

      最新开发

      开发排行榜