2013-07-24 5 views
0

У меня возникли некоторые проблемы с пониманием того, как работает обратный вызов звука SDL. У меня есть этот простой код, который должен генерировать простую квадратную волну:Проблемы с SDL Audio (нет вывода)

#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. Мне просто нужно, чтобы эти образцы правильно направлялись в звуковой буфер.

ответ

0

stream необходимо присвоить actual.format -местный тип данных, а затем перезаписать значения в stream с помощью образцов len/sizeof(<format's datatype>).

Квадратную волну будет трудно услышать, потому что данный алгоритм будет генерировать только короткий импульс каждые 7,1 млн. Выборок (~ 5 минут при 22050 Гц), когда обтекает 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; 
}