代码之家  ›  专栏  ›  技术社区  ›  Chilly Zhong

如何在iPhone上使用OpenAL播放循环声音

  •  4
  • Chilly Zhong  · 技术社区  · 16 年前

    我正在学习一个关于使用OpenAL播放声音的教程。现在一切都很好,除了我不能使声音循环。我相信我用过 AL_LOOPING 对于来源。现在它只能播放一次,当播放结束时,应用程序将被阻止(不会响应我点击播放按钮)。你知道代码出了什么问题吗?

    // 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;
        }
    }
    
    1 回复  |  直到 16 年前
        1
  •  0
  •   pestilence669    16 年前

    您应该能够在调用alBufferData()之后立即释放outData。它排除了它的罪魁祸首,您可以尝试静态扩展并自己管理内存。有点像:

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