Problems with SDL Audio (No output)

I'm facing some problems with understanding how the SDL audio callback works. I have this simple code, which should generate a simple square wave:

#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: %sn", SDL_GetError ());
                exit (-1);
        }
        SDL_PauseAudio (0);//Start the audio
}

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

}

I know that the callback is not done right, because I have no idea how to output to the buffer. Each time the callback is called, the first part of the callback function code generates the new sample, and stores it in the variabile Out.

Can anyone here modify this code so that the new samples go from Out to the correct position in the audio buffer? Also, I don't want to have the code modified in a very super-complex way just to generate the square wave - I have already taken care of that. The wave is generated correctly, each new sample appearing in the variable Out. I just need these samples to be routed correctly to the audio buffer.


You need to cast stream to a actual.format -appropriate datatype and then overwrite the values in stream with len / sizeof( <format's datatype> ) samples.

The square-wave will be kinda hard to hear because the given algorithm will only generate a brief high pulse every ~7.1 million samples (~5 minutes @22050Hz) when phase wraps around.

Try something like this:

#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;
}
链接地址: http://www.djcxy.com/p/33824.html

上一篇: 我有音频样本; 如何使用SDL正确播放它们?

下一篇: SDL音频问题(无输出)