1

SDL オーディオ コールバックの仕組みを理解する上で、いくつかの問題に直面しています。単純な方形波を生成するこの単純なコードがあります。

#include "SDL.h"
#include "SDL_audio.h"
#include <stdlib.h>
#include <math.h>

SDL_Surface *screen;
SDL_AudioSpec spec;
Uint32 sound_len=512;
Uint8 *sound_buffer;
int sound_pos = 0;
int counter;

unsigned int phase_delta=600;
unsigned int phase;
unsigned char out;

//Initialization
void init_sdl (void)
{
        if (SDL_Init (SDL_INIT_VIDEO|SDL_INIT_AUDIO) < 0)
                exit (-1);
        atexit (SDL_Quit);
        screen = SDL_SetVideoMode (640, 480, 16, SDL_HWSURFACE);
        if (screen == NULL)
                exit (-1);
}

//Generates a new sample and outputs it to the audio card
void Callback (void *userdata, Uint8 *stream, int len)
{

        Uint8 *waveptr;

        //Generates a new sample
        phase+=phase_delta;
        if ((phase>>8)<127) out=255; else out=0;
        //End

        //Output the current sample to the audio card
        waveptr = sound_buffer;
        SDL_MixAudio(stream, waveptr, 1, SDL_MIX_MAXVOLUME);

}

void play (void)
{
        sound_buffer = new Uint8[512];
        sound_len= 512;
        spec.freq = 22050;
        spec.format = AUDIO_S16SYS;
        spec.channels = 1;
        spec.silence = 0;
        spec.samples = 512;
        spec.padding = 0;
        spec.size = 0;
        spec.userdata = 0;

        spec.callback = Callback;
        if (SDL_OpenAudio (&spec, NULL) < 0)
        {       //Throw an error
                printf ("I don't think you like this: %s\n", SDL_GetError ());
                exit (-1);
        }
        SDL_PauseAudio (0);//Start the audio
}

int main(int argc, char* argv[])
{
        init_sdl ();
        play ();
        SDL_Delay (250);
        return 0;

}

バッファに出力する方法がわからないため、コールバックが正しく行われていないことはわかっています。コールバックが呼び出されるたびに、コールバック関数コードの最初の部分が新しいサンプルを生成し、それを変数 Out に格納します。

新しいサンプルが Out からオーディオ バッファの正しい位置に移動するように、このコードを変更できる人はいますか? また、方形波を生成するためだけに非常に複雑な方法でコードを変更したくありません - 私はすでにそれを処理しています。波形が正しく生成され、新しいサンプルがそれぞれ変数 Out に表示されます。これらのサンプルをオーディオ バッファに正しくルーティングする必要があるだけです。

4

1 に答える 1

0

適切なデータ型にキャストstreamしてから、値をサンプルで上書きする必要があります。actual.formatstreamlen / sizeof( <format's datatype> )

与えられたアルゴリズムは、ラップアラウンド時に〜710万サンプル(〜5分@22050Hz)ごとに短い高パルスのみを生成するため、方形波は聞き取りにくいでしょうphase

次のようなことを試してください:

#include <SDL.h>
#include <SDL_audio.h>
#include <iostream>

using namespace std;

//Generates new samples and outputs them to the audio card
void Callback( void* userdata, Uint8* stream, int len )
{
    // the format of stream depends on actual.format in main()
    // we're assuming it's AUDIO_S16SYS
    short* samples = reinterpret_cast< short* >( stream );
    size_t numSamples = len / sizeof( short );

    const unsigned int phase_delta = 600;
    static unsigned int phase = 0;

    // loop over all our samples
    for( size_t i = 0; i < numSamples; ++i )
    {
        phase+=phase_delta;
        short out = 0;
        if ((phase>>8)<127) out=SHRT_MAX; else out=0;  

        samples[i] = out;
    }
}

int main( int argc, char* argv[] )
{
    if( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_AUDIO ) < 0 )
        return -1;
    atexit( SDL_Quit );

    SDL_Surface* screen = SDL_SetVideoMode( 640, 480, 16, SDL_ANYFORMAT );
    if( screen == NULL)
        return -1;

    SDL_AudioSpec spec;
    spec.freq = 22050;
    spec.format = AUDIO_S16SYS;
    spec.channels = 1;
    spec.samples = 4096;
    spec.callback = Callback;
    spec.userdata = NULL;
    SDL_AudioSpec actual;
    if( SDL_OpenAudio( &spec, &actual ) < 0 )
    {
        cerr << "I don't think you like this: " << SDL_GetError() << endl;
        return -1;
    }
    if( spec.format != actual.format )
    {
        cerr << "format mismatch!" << endl;
        return -1;
    }

    SDL_PauseAudio( 0 );

    SDL_Event ev;
    while( SDL_WaitEvent( &ev ) )
    {
        if( ev.type == SDL_QUIT )
            break;
    }

    SDL_CloseAudio();
    SDL_Quit();
    return 0;
}
于 2013-07-25T21:28:38.840 に答える