仅在没有循环的情况下从阵列播放音频一次

时间:2014-06-26 17:01:29

标签: ios core-audio audiounit

我在音频编程方面完全是初学者,现在我正在玩AudioUnit。我跟随http://www.cocoawithlove.com/2010/10/ios-tone-generator-introduction-to.html并且已移植代码以使用iOS7。问题是我只想让它一次播放生成的正弦波,而不是继续播放声波。我不知道如何实现这一点。

生成音频样本:

    OSStatus RenderTone(
        void *inRefCon, 
        AudioUnitRenderActionFlags *ioActionFlags, 
        const AudioTimeStamp *inTimeStamp, 
        UInt32 inBusNumber, 
        UInt32 inNumberFrames, 
        AudioBufferList *ioData)

    {
        // Fixed amplitude is good enough for our purposes
        const double amplitude = 0.25;

        // Get the tone parameters out of the view controller
        ToneGeneratorViewController *viewController =
            (ToneGeneratorViewController *)inRefCon;
        double theta = viewController->theta;
        double theta_increment =
            2.0 * M_PI * viewController->frequency / viewController->sampleRate;

        // This is a mono tone generator so we only need the first buffer
        const int channel = 0;
        Float32 *buffer = (Float32 *)ioData->mBuffers[channel].mData;

        // Generate the samples
        for (UInt32 frame = 0; frame < inNumberFrames; frame++) 
        {
            buffer[frame] = sin(theta) * amplitude;

            theta += theta_increment;
            if (theta > 2.0 * M_PI)
            {
                theta -= 2.0 * M_PI;
            }
        }

        // Store the updated theta back in the view controller
        viewController->theta = theta;

        return noErr;
    }

创建AudioUnit:

// Configure the search parameters to find the default playback output unit
// (called the kAudioUnitSubType_RemoteIO on iOS but
// kAudioUnitSubType_DefaultOutput on Mac OS X)
AudioComponentDescription defaultOutputDescription;
defaultOutputDescription.componentType = kAudioUnitType_Output;
defaultOutputDescription.componentSubType = kAudioUnitSubType_RemoteIO;
defaultOutputDescription.componentManufacturer = kAudioUnitManufacturer_Apple;
defaultOutputDescription.componentFlags = 0;
defaultOutputDescription.componentFlagsMask = 0;

// Get the default playback output unit
AudioComponent defaultOutput = AudioComponentFindNext(NULL, &defaultOutputDescription);
NSAssert(defaultOutput, @"Can't find default output");

// Create a new unit based on this that we'll use for output
OSErr err = AudioComponentInstanceNew(defaultOutput, &toneUnit);
NSAssert1(toneUnit, @"Error creating unit: %ld", err);

// Set our tone rendering function on the unit
AURenderCallbackStruct input;
input.inputProc = RenderTone;
input.inputProcRefCon = self;
err = AudioUnitSetProperty(toneUnit, 
    kAudioUnitProperty_SetRenderCallback, 
    kAudioUnitScope_Input,
    0, 
    &input, 
    sizeof(input));
NSAssert1(err == noErr, @"Error setting callback: %ld", err);

// Set the format to 32 bit, single channel, floating point, linear PCM
const int four_bytes_per_float = 4;
const int eight_bits_per_byte = 8;
AudioStreamBasicDescription streamFormat;
streamFormat.mSampleRate = sampleRate;
streamFormat.mFormatID = kAudioFormatLinearPCM;
streamFormat.mFormatFlags =
    kAudioFormatFlagsNativeFloatPacked | kAudioFormatFlagIsNonInterleaved;
streamFormat.mBytesPerPacket = four_bytes_per_float;
streamFormat.mFramesPerPacket = 1;    
streamFormat.mBytesPerFrame = four_bytes_per_float;        
streamFormat.mChannelsPerFrame = 1;    
streamFormat.mBitsPerChannel = four_bytes_per_float * eight_bits_per_byte;
err = AudioUnitSetProperty (toneUnit,
    kAudioUnitProperty_StreamFormat,
    kAudioUnitScope_Input,
    0,
    &streamFormat,
    sizeof(AudioStreamBasicDescription));
NSAssert1(err == noErr, @"Error setting stream format: %ld", err);

谢谢!

1 个答案:

答案 0 :(得分:0)

  

问题是我只想让它一次播放生成的正弦波

你应该做的是在一段时间后停止音频单元。

例如,您可以在拨打NSTimer时设置AudioOutputUnitStart,然后当计时器触发时,您拨打AudioOutputUnitStop(实际上是您的音频设备处理代码)。更简单的是,您可以使用performSelector:withObject:afterDelay:并调用音频单元处理方法。

希望这有帮助。