嘿大家,我现在正试图弄清楚如何播放我用正弦波产生的音调。
这是我的代码:
#include <iostream>
#include <OpenAL/al.h>
#include <OpenAL/alc.h>
#include <Math.h>
using namespace std;
int main (int argc, char * const argv[]) {
int number = 0;
int i, size;
double const Pi=4*atan(1);
cout << "Enter number of seconds:" << endl;
scanf("%d", &number);
size = 44100*number;
unsigned char buffer [size]; //buffer array
for(i = 0; i < size; i++){
buffer[i] = (char)sin((2*Pi*440)/(44100*i))*127;
}
return 0;
}
显然它目前没有做任何事情,因为我不知道如何播放缓冲区。 我不想生成一个wav文件,也不想加载一个。我只是想回放我生成的缓冲区。
我目前正在使用Mac OS X,并尝试使用OpenAL方法 - 但是我发现alut和alu不再是它的一部分了,如果我尝试使用它,那么事实证明它无论如何都被摧毁了。 我也尝试过包含QAudioOutput,但出于某种原因,它似乎并不在我的Mac上。
我只想简单播放我创作的音色。有没有人能指点我的东西?
谢谢堆!!!
答案 0 :(得分:12)
我为此准确写了一个例子。在MacOSX下使用OpenAL运行良好,并播放流畅的正弦。看看这里: http://ioctl.eu/blog/2011/03/16/openal-sine-synth/
代码很短,我想我可以在这里添加它也是为了完整性:
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <OpenAL/al.h>
#include <OpenAL/alc.h>
#define CASE_RETURN(err) case (err): return "##err"
const char* al_err_str(ALenum err) {
switch(err) {
CASE_RETURN(AL_NO_ERROR);
CASE_RETURN(AL_INVALID_NAME);
CASE_RETURN(AL_INVALID_ENUM);
CASE_RETURN(AL_INVALID_VALUE);
CASE_RETURN(AL_INVALID_OPERATION);
CASE_RETURN(AL_OUT_OF_MEMORY);
}
return "unknown";
}
#undef CASE_RETURN
#define __al_check_error(file,line) \
do { \
ALenum err = alGetError(); \
for(; err!=AL_NO_ERROR; err=alGetError()) { \
std::cerr << "AL Error " << al_err_str(err) << " at " << file << ":" << line << std::endl; \
} \
}while(0)
#define al_check_error() \
__al_check_error(__FILE__, __LINE__)
void init_al() {
ALCdevice *dev = NULL;
ALCcontext *ctx = NULL;
const char *defname = alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
std::cout << "Default device: " << defname << std::endl;
dev = alcOpenDevice(defname);
ctx = alcCreateContext(dev, NULL);
alcMakeContextCurrent(ctx);
}
void exit_al() {
ALCdevice *dev = NULL;
ALCcontext *ctx = NULL;
ctx = alcGetCurrentContext();
dev = alcGetContextsDevice(ctx);
alcMakeContextCurrent(NULL);
alcDestroyContext(ctx);
alcCloseDevice(dev);
}
int main(int argc, char* argv[]) {
/* initialize OpenAL */
init_al();
/* Create buffer to store samples */
ALuint buf;
alGenBuffers(1, &buf);
al_check_error();
/* Fill buffer with Sine-Wave */
float freq = 440.f;
int seconds = 4;
unsigned sample_rate = 22050;
size_t buf_size = seconds * sample_rate;
short *samples;
samples = new short[buf_size];
for(int i=0; i<buf_size; ++i) {
samples[i] = 32760 * sin( (2.f*float(M_PI)*freq)/sample_rate * i );
}
/* Download buffer to OpenAL */
alBufferData(buf, AL_FORMAT_MONO16, samples, buf_size, sample_rate);
al_check_error();
/* Set-up sound source and play buffer */
ALuint src = 0;
alGenSources(1, &src);
alSourcei(src, AL_BUFFER, buf);
alSourcePlay(src);
/* While sound is playing, sleep */
al_check_error();
sleep(seconds);
/* Dealloc OpenAL */
exit_al();
al_check_error();
return 0;
}
更新:我发现OpenAL对我的需求有点限制,比如我在低延迟播放时遇到一些问题,因为这似乎不是OpenAL的主要域。相反,我发现了非常有说服力的PortAudio:http://www.portaudio.com/ 它支持所有主要平台(Mac,Win,Unix / ALSA),看起来非常好。有一个正弦播放的例子,它更复杂,但非常简单。只需下载最新版本并在test / patest_sine.c找到正弦播放样本
答案 1 :(得分:0)
您需要通过操作系统播放声音。它并不像你想象的那么简单。在OSX中,您需要通过CoreAudio。
更好的方法是使用像PortAudio(http://www.portaudio.com/)这样的包装器库,这将使您的代码更具可移植性,并为您节省一些从程序中获取声音所需的样板。
答案 2 :(得分:0)
试试这个(这个程序使用Z transform concept,一个使用ALSA生成dtmf音并在LINUX上可编译的完整示例here):
/*
* Cosine Samples Generator
*
* Autor: Volnei Klehm
* Data: 04/01/2014
*/
#include <math.h>
#include <stdio.h>
#define S_FREQ 8000 /*Sample frequency, should be greater thar 2*sineFrequency
If using audio output it has to be the same saple frequency
Used there*/
const float frequency_in_Hertz = 697; /*set output frequency*/
const float generatorContant1 = cosf(2*M_PI*(frequency_in_Hertz/S_FREQ));
const float generatorContant2 = sinf(2*M_PI*(frequency_in_Hertz/S_FREQ));
float GenerateSignal(){
static float Register[2]={1,0};
static float FeedBack;
FeedBack=2*generatorContant1*Register[0]-Register[1];
Register[1]=Register[0];
Register[0]=FeedBack;
return (generatorContant2*Register[1]);
}
int main(void) {
/*generate 300 samples*/
for (int NumberOfSamples = 300; NumberOfSamples > 0; NumberOfSamples--)
printf("\n%f", GenerateSignal());
return 0;
}