lien de Davide Vosti à http://lists.apple.com/archives/coreaudio-api/2008/Dec/msg00173.html ne fonctionne plus, puisque les listes d'Apple semblent ne pas répondre. Voici le cache de Google pour l'exhaustivité.
//
// AudioUnitTestAppDelegate.m
// AudioUnitTest
//
// Created by Marc Vaillant on 11/25/08.
// Copyright __MyCompanyName__ 2008. All rights reserved.
//
#import "AudioUnitTestAppDelegate.h"
#include <AudioUnit/AudioUnit.h>
//#include "MachTimer.hpp"
#include <vector>
#include <iostream>
using namespace std;
#define kOutputBus 0
#define kInputBus 1
#define SAMPLE_RATE 44100
vector<int> _pcm;
int _index;
@implementation AudioUnitTestAppDelegate
@synthesize window;
void generateTone(
vector<int>& pcm,
int freq,
double lengthMS,
int sampleRate,
double riseTimeMS,
double gain)
{
int numSamples = ((double) sampleRate) * lengthMS/1000.;
int riseTimeSamples = ((double) sampleRate) * riseTimeMS/1000.;
if(gain > 1.)
gain = 1.;
if(gain < 0.)
gain = 0.;
pcm.resize(numSamples);
for(int i = 0; i < numSamples; ++i)
{
double value = sin(2. * M_PI * freq * i/sampleRate);
if(i < riseTimeSamples)
value *= sin(i * M_PI/(2.0 * riseTimeSamples));
if(i > numSamples - riseTimeSamples - 1)
value *= sin(2. * M_PI * (i - (numSamples - riseTimeSamples) + riseTimeSamples)/ (4. * riseTimeSamples));
pcm[i] = (int) (value * 32500.0 * gain);
pcm[i] += (pcm[i]<<16);
}
}
static OSStatus playbackCallback(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData)
{
cout<<"index = "<<_index<<endl;
cout<<"numBuffers = "<<ioData->mNumberBuffers<<endl;
int totalNumberOfSamples = _pcm.size();
for(UInt32 i = 0; i < ioData->mNumberBuffers; ++i)
{
int samplesLeft = totalNumberOfSamples - _index;
int numSamples = ioData->mBuffers[i].mDataByteSize/4;
if(samplesLeft > 0)
{
if(samplesLeft < numSamples)
{
memcpy(ioData->mBuffers[i].mData, &_pcm[_index], samplesLeft * 4);
_index += samplesLeft;
memset((char*) ioData->mBuffers[i].mData + samplesLeft * 4, 0, (numSamples - samplesLeft) * 4) ;
}
else
{
memcpy(ioData->mBuffers[i].mData, &_pcm[_index], numSamples * 4) ;
_index += numSamples;
}
}
else
memset(ioData->mBuffers[i].mData, 0, ioData->mBuffers[i].mDataByteSize);
}
return noErr;
}
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
//generate pcm tone freq = 800, duration = 1s, rise/fall time = 5ms
generateTone(_pcm, 800, 1000, SAMPLE_RATE, 5, 0.8);
_index = 0;
OSStatus status;
AudioComponentInstance audioUnit;
// Describe audio component
AudioComponentDescription desc;
desc.componentType = kAudioUnitType_Output;
desc.componentSubType = kAudioUnitSubType_RemoteIO;
desc.componentFlags = 0;
desc.componentFlagsMask = 0;
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
// Get component
AudioComponent inputComponent = AudioComponentFindNext(NULL, &desc);
// Get audio units
status = AudioComponentInstanceNew(inputComponent, &audioUnit);
//checkStatus(status);
UInt32 flag = 1;
// Enable IO for playback
status = AudioUnitSetProperty(audioUnit,
kAudioOutputUnitProperty_EnableIO,
kAudioUnitScope_Output,
kOutputBus,
&flag,
sizeof(flag));
//checkStatus(status);
// Describe format
AudioStreamBasicDescription audioFormat;
audioFormat.mSampleRate = SAMPLE_RATE;
audioFormat.mFormatID = kAudioFormatLinearPCM;
audioFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
audioFormat.mFramesPerPacket = 1;
audioFormat.mChannelsPerFrame = 2;
audioFormat.mBitsPerChannel = 16;
audioFormat.mBytesPerPacket = 4;
audioFormat.mBytesPerFrame = 4;
// Apply format
status = AudioUnitSetProperty(audioUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input,
kOutputBus,
&audioFormat,
sizeof(audioFormat));
// checkStatus(status);
// Set output callback
AURenderCallbackStruct callbackStruct;
callbackStruct.inputProc = playbackCallback;
callbackStruct.inputProcRefCon = self;
status = AudioUnitSetProperty(audioUnit,
kAudioUnitProperty_SetRenderCallback,
kAudioUnitScope_Global,
kOutputBus,
&callbackStruct,
sizeof(callbackStruct));
// Initialize
status = AudioUnitInitialize(audioUnit);
// Start playing
status = AudioOutputUnitStart(audioUnit);
[window makeKeyAndVisible];
}
- (void)dealloc {
[window release];
[super dealloc];
}
@end
Ceci est incorrect. Vous ne devez pas appeler AudioQueueCallback dans la boucle d'allocation. Je ne crois pas que la description soit correcte, non plus. De plus, vous devriez appeler AudioQueueStart (audioQueue, nil) au lieu de cette façon étrange. Regardez plutôt le cadre AudioUnit. – thefaj
@thefaj: Je crois que vous êtes celui qui est incorrect. Cet exemple est tiré de mon application SC68 Player (http://itunes.apple.com/se/app/sc68-player/id295290413?mt=8), où j'ai initialement pris le code pour la relecture audio à partir de l'exemple de l'application iPhone d'Apple SpeakHere (http://developer.apple.com/iphone/library/samplecode/SpeakHere/), regardez le fichier AQPlayer.mm. Le code source complet du lecteur SC68 est disponible (http://www.peylow.se/sc68player.html). – PeyloW
Votre exemple ne contient pas AudioQueueStart() qui doit être appelé comme AudioQueueCallback. – thefaj