How to use an Audio Unit on the iPhone

泪湿孤枕 提交于 2019-12-03 00:41:00

There are some very good resources here (http://michael.tyson.id.au/2008/11/04/using-remoteio-audio-unit/) for using the RemoteIO Audio Unit. In my experience working with Audio Units on the iPhone, I've found that I can implement a transformation manually in the callback function. In doing so, you might find that solves you problem.

Regarding changing pitch on the iPhone, OpenAL is the way to go. Check out the SoundManager class available from www.71squared.com for a great example of an OpenAL sound engine that supports pitch.

Kemo
- (void)modifySpeedOf:(CFURLRef)inputURL byFactor:(float)factor andWriteTo:(CFURLRef)outputURL {

    ExtAudioFileRef inputFile = NULL;
    ExtAudioFileRef outputFile = NULL;

    AudioStreamBasicDescription destFormat;

    destFormat.mFormatID = kAudioFormatLinearPCM;
    destFormat.mFormatFlags = kAudioFormatFlagsCanonical;
    destFormat.mSampleRate = 44100 * factor;
    destFormat.mBytesPerPacket = 2;
    destFormat.mFramesPerPacket = 1;
    destFormat.mBytesPerFrame = 2;
    destFormat.mChannelsPerFrame = 1;
    destFormat.mBitsPerChannel = 16;
    destFormat.mReserved = 0;

    ExtAudioFileCreateWithURL(outputURL, kAudioFileCAFType,
                              &destFormat, NULL, kAudioFileFlags_EraseFile, &outputFile);

    ExtAudioFileOpenURL(inputURL, &inputFile);

    //find out how many frames is this file long
    SInt64 length = 0;
    UInt32 dataSize2 = (UInt32)sizeof(length);
    ExtAudioFileGetProperty(inputFile,
                            kExtAudioFileProperty_FileLengthFrames, &dataSize2, &length);

    SInt16 *buffer = (SInt16*)malloc(kBufferSize * sizeof(SInt16));

    UInt32 totalFramecount = 0;

    AudioBufferList bufferList;
    bufferList.mNumberBuffers = 1;
    bufferList.mBuffers[0].mNumberChannels = 1;
    bufferList.mBuffers[0].mData = buffer; // pointer to buffer of audio data
    bufferList.mBuffers[0].mDataByteSize = kBufferSize *
    sizeof(SInt16); // number of bytes in the buffer

    while(true) {

        UInt32 frameCount = kBufferSize * sizeof(SInt16) / 2;
        // Read a chunk of input
        ExtAudioFileRead(inputFile, &frameCount, &bufferList);
        totalFramecount += frameCount;

        if (!frameCount || totalFramecount >= length) {
            //termination condition
            break;
        }
        ExtAudioFileWrite(outputFile, frameCount, &bufferList);
    }

    free(buffer);

    ExtAudioFileDispose(inputFile);
    ExtAudioFileDispose(outputFile);

}

it will change pitch based on factor

I've used the NewTimePitch audio unit for this before, the Audio Component Description for that is

var newTimePitchDesc = AudioComponentDescription(componentType: kAudioUnitType_FormatConverter,
        componentSubType: kAudioUnitSubType_NewTimePitch,
        componentManufacturer: kAudioUnitManufacturer_Apple,
        componentFlags: 0,
        componentFlagsMask: 0)

then you can change the pitch parameter with an AudioUnitSetParamater call. For example this changes the pitch by -1000 cents

err = AudioUnitSetParameter(newTimePitchAudioUnit,
        kNewTimePitchParam_Pitch,
        kAudioUnitScope_Global,
        0,
        -1000,
        0)

The parameters for this audio unit are as follows

    // Parameters for AUNewTimePitch
enum {
      // Global, rate, 1/32 -> 32.0, 1.0
  kNewTimePitchParam_Rate                         = 0,
      // Global, Cents, -2400 -> 2400, 1.0
  kNewTimePitchParam_Pitch                        = 1,
      // Global, generic, 3.0 -> 32.0, 8.0
  kNewTimePitchParam_Overlap                      = 4,
      // Global, Boolean, 0->1, 1
  kNewTimePitchParam_EnablePeakLocking            = 6
};

but you'll only need to change the pitch parameter for your purposes. For a guide on how to implement this refer to Justin's answer

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!