6

こんにちは、私は現在、正弦波を使用して生成したトーンを再生する方法を見つけようとしています。

これが私のコードです:

#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 のどこにもないようです。

作成したトーンを簡単に再生したいだけです。誰かが私に指摘できることはありますか?

ありがとうございます!

4

3 に答える 3

14

私はまさにこのための例を書きました。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 で sine-playback サンプルを見つけてください。

于 2011-03-29T08:04:21.657 に答える
0

サウンドを再生するには、OS を経由する必要があります。あなたが思うほど簡単ではありません。OSX では、CoreAudio を経由する必要があります。

より良いアプローチは、PortAudio (http://www.portaudio.com/) のようなラッパー ライブラリを使用することです。これにより、コードの移植性が向上し、プログラムから音を出すために必要なボイラープレートの一部を節約できます。

于 2011-03-29T07:14:55.090 に答える