Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/156.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 播放';的简单示例;。wav';在c+中与alsa库同时进行音频传输+;?_C++_Audio_Sdl 2_Playback_Libalsa - Fatal编程技术网

C++ 播放';的简单示例;。wav';在c+中与alsa库同时进行音频传输+;?

C++ 播放';的简单示例;。wav';在c+中与alsa库同时进行音频传输+;?,c++,audio,sdl-2,playback,libalsa,C++,Audio,Sdl 2,Playback,Libalsa,我正在用电脑键盘制作一架钢琴,我需要同时播放“.wav”音频 我使用SFML/Audio.hpp和SDL2/SDL_mixer.h libs成功地做到了这一点,但是下面代码的PlayAudio::play()函数播放音频需要几毫秒的时间,延迟几乎是不可察觉的。然而,当钢琴以高速播放时,我注意到了存在的小延迟 例如: #include <SFML / Audio.hpp> #include <SDL2 / SDL_mixer.h> #include "PlayAudio.h

我正在用电脑键盘制作一架钢琴,我需要同时播放“.wav”音频

我使用SFML/Audio.hpp和SDL2/SDL_mixer.h libs成功地做到了这一点,但是下面代码的PlayAudio::play()函数播放音频需要几毫秒的时间,延迟几乎是不可察觉的。然而,当钢琴以高速播放时,我注意到了存在的小延迟

例如:

#include <SFML / Audio.hpp>
#include <SDL2 / SDL_mixer.h>
#include "PlayAudio.h"

sf :: SoundBuffer buffer [10];
sf :: Sound pad [10];

void PlayAudio :: loadBank () {
  buffer [0] .loadFromFile ("src / audiosExa / a1.wav");
  pad [0] .setBuffer (buffer [0]);

  buffer [1] .loadFromFile ("src / audiosExa / a2.wav");
  pad [1] .setBuffer (buffer [1]);

  buffer [2] .loadFromFile ("src / audiosExa / a3.wav");
  pad [2] .setBuffer (buffer [2]);

   buffer [3] .loadFromFile ("src / audiosExa / a4.wav");
   pad [3] .setBuffer (buffer [3]);
};

void PlayAudio :: play (int i) {
  pad [i] .play ();
};
#包括
#包括
#包括“PlayAudio.h”
sf::声音缓冲区[10];
sf::声控板[10];
void PlayAudio::loadBank(){
缓冲区[0].loadFromFile(“src/audiosExa/a1.wav”);
pad[0].setBuffer(缓冲区[0]);
缓冲区[1].loadFromFile(“src/audiosExa/a2.wav”);
pad[1].setBuffer(缓冲区[1]);
缓冲区[2].loadFromFile(“src/audiosExa/a3.wav”);
pad[2].setBuffer(缓冲区[2]);
缓冲区[3].loadFromFile(“src/audiosExa/a4.wav”);
pad[3].setBuffer(缓冲区[3]);
};
void PlayAudio::play(int i){
pad[i].play();
};

所以我想做同样的过程,但使用alsa lib,它似乎更快,但我设法一次发出一个声音,而我不能同时发出音频。我尝试使用线程,但只有在另一个声音结束后才会发出声音。

几个月后,有可能以非常简单的方式解决这个大问题。。。在上面提到的代码中,我只使用了SFML库,不幸的是,正如我已经评论的那样,它有很高的延迟。。。lib-SDL-it根本没有被使用,只是被导入了。我重新编写了代码,这次只使用SDL库,除了获得出色的延迟外,我还设法使音频同时播放。请按照以下教程操作:

我对代码做了一些小改动,只在Linux上使用


ALSA库的使用相当复杂,因为其级别非常低。如果您不需要非常快的音频,请将上面的代码与lib-SFML一起使用,因为它非常容易实现,也很快实现,否则使用SDL您将获得成功。

几个月后,有可能以非常简单的方式解决大问题。。。在上面提到的代码中,我只使用了SFML库,不幸的是,正如我已经评论的那样,它有很高的延迟。。。lib-SDL-it根本没有被使用,只是被导入了。我重新编写了代码,这次只使用SDL库,除了获得出色的延迟外,我还设法使音频同时播放。请按照以下教程操作:

我对代码做了一些小改动,只在Linux上使用


ALSA库的使用相当复杂,因为其级别非常低。如果您不需要非常快的音频,请将上面的代码与lib-SFML一起使用,因为它很容易实现,也很快实现,否则使用SDL将获得成功。

您可以采取几种不同的方法在应用程序中获得合成音。要么你自己做混音,要么让ALSA为你做混音

也许最简单的方法(也是最耗费资源的方法)是让ALSA为您进行混合。在这种情况下,为每个焊盘打开一次ALSA dmix插件。您可以为每个焊盘创建一个类并对其进行线程化,以便它们独立运行。每个类将音频数据加载到缓冲区,当触发时,将其播放回ALSA dmix插件。下面是一个示例(使用它提供C++ LIbSOX音频文件处理、线程和ALSA处理):

#包括
#包括)它看起来类似于以下代码段:

常量字符串deviceName=“hw:0,0”//也可以是“默认值” 播放播放(deviceName.c_str());//打开播放设备 //配置播放设备的参数 Sox sox1,sox2;//实例化两个音频文件读取器(libsox) int-ret=sox1.openRead(“src/audiosExa/a1.wav”);//将音频加载到特征阵列数据缓冲区 本征::阵列pad1,pad2; sox1.read(pad1); ret=sox2.openRead(“src/audiosExa/a2.wav”); sox2.read(pad2); //现在循环到持续输出,使用EXBUFF对所有需要输出的焊盘求和 本征::阵列突发; while(继续){ //通过在此处添加部分焊盘来构造输出缓冲区 //类似于:exputf=pad1.block(…)+pad2.block(…)
播放您可以采取几种不同的方法在应用程序中获得复调声音。您可以自己进行混音,也可以让ALSA为您进行混音

可能是最简单的方法(也是最耗费资源的方法)让ALSA为您进行混音。在这种情况下,您可以为每个pad打开一次ALSA dmix插件。您可以为每个pad创建一个类并对其执行线程,使其独立运行。每个类将音频数据加载到缓冲区,当触发时将其播放回ALSA dmix插件。下面是一个示例(使用C++提供LIbSOX音频文件处理、线程和ALSA处理):

#包括
#包括)它看起来类似于以下代码段:

const string deviceName=“hw:0,0”;//也可以是“默认值”
播放播放(deviceName.c_str());//打开播放设备
//配置播放设备的参数
Sox sox1,sox2;//实例化两个音频文件读取器(libsox)
int ret=sox1.openRead(“src/audiosExa/a1.wav”);//将音频加载到特征数组数据缓冲区
本征::阵列pad1,pad2;
sox1.read(pad1);
ret=sox2.openRead(“src/audiosExa/a2.wav”);
sox2.read(pad2);
//现在循环到持续输出,使用EXBUFF对所有需要输出的焊盘求和
本征::阵列突发;
while(继续){
//通过在此处添加部分焊盘来构造输出缓冲区
//类似于:exputf=pad1.block(…)+pad2.block(…)
回放
#include <Sox.H>
#include <ALSA.H>
#include <Thread.H>
using namespace ALSA;

class Pad : public PlayBack, WaitingThread {
  Eigen::Array<int, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> audio; // the Eigen array which holds the audio buffer

public:

  /// Constructor opens the audio plawyback device and reads in the audio file data
  Pad(char* devName, string audioFile) : PlayBack(devName) {
    Sox<int> sox; // instantiate libsox
    sox.openRead(audioFile); // open the audio file to read
    sox.read(audio); // read in the audio data
  }

  /// Configure the audio playback ([see here for example][2])
  configurePlayback(){
    // set channels, format, etc.
  }

  /// Playback the entire audio sound
  play(){
    *this<<audio; // stream the audio out through the PlayBack class
  }

  // In our threaded method, we wait to be signalled then we do playback, then wait again, [see here for examples on thread signalling][3]
  void *threadMain(void){
    while (continue) {
      cond.lock();
      cond.wait(); // wait till signalled
      play(); // playback the audio
      cond.unLock(); // unlock to be signalled again
    }
    return NULL;
  }
};

Pad pad1("dmix", "src/audiosExa/a1.wav"); // instantiate a pad
Pad pad2("dmix", "src/audiosExa/a2.wav"); // instantiate a pad
// in your UI thread, you need to run each of the Pad thread
pad1.run();
pad2.run();
// in your UI thread, you need to signal the waiting pad threads 
// Looks something like this for each pad
pad1.cond.lock(); pad1.cond.signal(); pad1.cond.unlock();
const string deviceName="hw:0,0"; // could also be "default"
Playback playBack(deviceName.c_str()); // open the playback device
// configure the parameters of the playback device
Sox<short int> sox1, sox2; // instantiate two audio file readers (libsox)
int ret=sox1.openRead("src/audiosExa/a1.wav"); // load in their audio to an Eigen Array data buffer
Eigen::Array<int, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> pad1, pad2;
sox1.read(pad1);
ret=sox2.openRead("src/audiosExa/a2.wav");
sox2.read(pad2);
// now loop to constantly output, using outBuf to sum all pads which require output
Eigen::Array<int, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> outBuf;
while (continue){
  // construct your output buffer by adding portions of your pads here
  // something like : outBuf=pad1.block(...)+pad2.block(...)
  playBack<<outBuf; // play the audio data
}