2013-07-24 5 views
0

SDL 오디오 콜백 작동 방법에 대한 몇 가지 문제점이 있습니다. 내가 버퍼로 출력하는 방법을 모르고이 없기 때문에, 내가 콜백 잘 수행되지 않는 것을 알고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; 

} 

: 나는 간단한 사각 파를 생성해야이 간단한 코드를 가지고있다. 콜백이 호출 될 때마다 콜백 함수 코드의 첫 번째 부분은 새 샘플을 생성하고이를 variabile Out에 저장합니다.

새 샘플이 오디오 버퍼의 올바른 위치에 출력되도록이 코드를 수정할 수 있습니까? 또한, 나는 구형파를 생성하기 위해 매우 복잡한 방법으로 코드를 수정하고 싶지 않습니다. 이미 이미 처리했습니다. 웨이브가 올바르게 생성되고 각각의 새 샘플이 변수 Out에 나타납니다. 이 샘플을 오디오 버퍼로 올바르게 라우팅하기 만하면됩니다.

답변

0

streamactual.format 적절한 데이터 형식으로 캐스팅 한 다음 stream의 값을 len/sizeof(<format's datatype>) 샘플로 덮어 써야합니다.

phase이 랩핑 될 때 주어진 알고리즘이 약 710 만 샘플 (~ 5 분 @ 22050Hz)마다 짧은 하이 펄스 만 생성하기 때문에 구형파는 다소 듣기 어려울 것입니다. 이 같은

시도 뭔가 :

#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; 
}