2009-12-09 8 views
4

OpenAL로 사운드를 재생하는 방법에 대한 자습서를 진행 중입니다. 이제는 사운드를 반복 할 수 없다는 것 외에는 모든 것이 잘 작동합니다. 나는 소스로 AL_LOOPING을 사용했다고 생각한다. 이제는 한 번만 재생할 수 있고 재생이 끝나면 앱이 차단됩니다 (재생 버튼에서 내 탭에 응답하지 않음). 코드의 문제점에 대한 아이디어가 있습니까?iPhone에서 OpenAL로 루핑 사운드를 재생하는 방법

// start up openAL 
// init device and context 
-(void)initOpenAL 
{ 
    // Initialization 
    mDevice = alcOpenDevice(NULL); // select the "preferred device" 
    if (mDevice) { 
     // use the device to make a context 
     mContext = alcCreateContext(mDevice, NULL); 
     // set my context to the currently active one 
     alcMakeContextCurrent(mContext); 
    } 
} 


// open the audio file 
// returns a big audio ID struct 
-(AudioFileID)openAudioFile:(NSString*)filePath 
{ 
    AudioFileID outAFID; 
    // use the NSURl instead of a cfurlref cuz it is easier 
    NSURL * afUrl = [NSURL fileURLWithPath:filePath]; 

    // do some platform specific stuff.. 
#if TARGET_OS_IPHONE 
    OSStatus result = AudioFileOpenURL((CFURLRef)afUrl, kAudioFileReadPermission, 0, &outAFID); 
#else 
    OSStatus result = AudioFileOpenURL((CFURLRef)afUrl, fsRdPerm, 0, &outAFID); 
#endif 
    if (result != 0) NSLog(@"cannot openf file: %@",filePath); 
    return outAFID; 
} 


// find the audio portion of the file 
// return the size in bytes 
-(UInt32)audioFileSize:(AudioFileID)fileDescriptor 
{ 
    UInt64 outDataSize = 0; 
    UInt32 thePropSize = sizeof(UInt64); 
    OSStatus result = AudioFileGetProperty(fileDescriptor, kAudioFilePropertyAudioDataByteCount, &thePropSize, &outDataSize); 
    if(result != 0) NSLog(@"cannot find file size"); 
    return (UInt32)outDataSize; 
} 

- (void)stopSound 
{ 
    alSourceStop(sourceID); 
} 

-(void)cleanUpOpenAL:(id)sender 
{ 
    // delete the sources 
    alDeleteSources(1, &sourceID); 

    // delete the buffers 
    alDeleteBuffers(1, &bufferID); 

    // destroy the context 
    alcDestroyContext(mContext); 

    // close the device 
    alcCloseDevice(mDevice); 
} 

-(IBAction)play:(id)sender 
{ 
    alSourcePlay(sourceID); 
} 


#pragma mark - 
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib. 
- (void)viewDidLoad { 
    [super viewDidLoad]; 

    [self initOpenAL]; 
    // get the full path of the file 
    NSString* fileName = [[NSBundle mainBundle] pathForResource:@"sound" ofType:@"caf"]; 
    // first, open the file 
    AudioFileID fileID = [self openAudioFile:fileName]; 

    // find out how big the actual audio data is 
    UInt32 fileSize = [self audioFileSize:fileID]; 

    // this is where the audio data will live for the moment 
    unsigned char * outData = malloc(fileSize); 

    // this where we actually get the bytes from the file and put them 
    // into the data buffer 
    OSStatus result = noErr; 
    result = AudioFileReadBytes(fileID, false, 0, &fileSize, outData); 
    AudioFileClose(fileID); //close the file 

    if (result != 0) NSLog(@"cannot load effect: %@", fileName); 

    //NSUInteger bufferID;    // buffer is defined in head file 
    // grab a buffer ID from openAL 
    alGenBuffers(1, &bufferID); 

    // jam the audio data into the new buffer 
    alBufferData(bufferID, AL_FORMAT_STEREO16, outData, fileSize, 8000); 


    //NSUInteger sourceID;    // source is defined in head file 

    // grab a source ID from openAL 
    alGenSources(1, &sourceID); 

    // attach the buffer to the source 
    alSourcei(sourceID, AL_BUFFER, bufferID); 
    // set some basic source prefs 
    alSourcef(sourceID, AL_PITCH, 1.0f); 
    alSourcef(sourceID, AL_GAIN, 1.0f); 
    alSourcei(sourceID, AL_LOOPING, AL_TRUE); 

    // clean up the buffer 
    if (outData) 
    { 
     free(outData); 
     outData = NULL; 
    } 
} 
+0

저는 이전 프로젝트 중 하나에서 비슷한 코드를 사용했는데 정상적으로 작동합니다. 사운드가 재생 된 후 앱 동작에 대해 더 자세히 설명해 주시겠습니까? UI를 완전히 차단하거나 버튼을 클릭 한 후에 아무 것도 일어나지 않습니까? – Morion

+0

재생 버튼을 누르면 아무 것도 발생하지 않습니다 (버튼이 파란색으로 표시되지 않음). 그리고 몇 초 후 (10 초 이상) 파란색으로 표시되고 전체가 차단됩니다. 앱을 닫으려면 홈 버튼을 눌러야합니다. –

+0

viewDidLoad에서 "outData"를 릴리스했기 때문입니까? 어쩌면 outData를 전용 변수로 정의하고 여기에 공개하지 않아야합니다. 감사합니다. –

답변

0

alBufferData() 호출 바로 다음에 outData를 릴리스 할 수 있어야합니다. 그것은 범인으로 그것을 제외, 당신은 정적 확장을 시도하고 직접 메모리를 관리 할 수 ​​있습니다. 그것은 다음과 같습니다 :

alBufferDataStaticProcPtr alBufferDataStaticProc = (alBufferDataStaticProcPtr)alcGetProcAddress(0, (const ALCchar *)"alBufferDataStatic"); 
alBufferDataStaticProc(bufferID, bitChanFormat, audioData, audioDataSize, dataFormat.mSampleRate); 
+0

. 사운드에 잘못된 형식을 지정하고 있습니다. alBufferDataStaticProc 메서드를 사용하면이 오류를 방지 할 수 있습니다. 정말 좋은 방법입니다. –

관련 문제