2010-05-21 17 views
3

Je suis en train d'écrire une application pour iPhone qui enregistre et lit des fichiers audio simultanément à l'aide de l'unité audio E/S, conformément au Apple's recommendations.kAudioFormatFlagIsFloat est-il pris en charge sur iPhoneOS?

Je souhaite appliquer des effets sonores (réverbération, etc.) sur l'audio enregistré avant de le lire. Pour que ces effets fonctionnent bien, j'ai besoin que les échantillons soient des nombres à virgule flottante, plutôt que des entiers. Il semble que cela devrait être possible, en créant un AudioStreamBasicDescription avec kAudioFormatFlagIsFloat sur mFormatFlags. C'est ce que mon code ressemble à:

AudioStreamBasicDescription streamDescription; 

streamDescription.mSampleRate = 44100.0; 
streamDescription.mFormatID = kAudioFormatLinearPCM; 
streamDescription.mFormatFlags = kAudioFormatFlagIsFloat; 
streamDescription.mBitsPerChannel = 32; 
streamDescription.mBytesPerFrame = 4; 
streamDescription.mBytesPerPacket = 4; 
streamDescription.mChannelsPerFrame = 1; 
streamDescription.mFramesPerPacket = 1; 
streamDescription.mReserved = 0; 

OSStatus status; 

status = AudioUnitSetProperty(audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamDescription, sizeof(streamDescription)); 
if (status != noErr) 
    fprintf(stderr, "AudioUnitSetProperty (kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input) returned status %ld\n", status); 

status = AudioUnitSetProperty(audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &streamDescription, sizeof(streamDescription)); 
if (status != noErr) 
    fprintf(stderr, "AudioUnitSetProperty (kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output) returned status %ld\n", status); 

Cependant, quand je lance ce (sur un iPhoneOS iPhone 3GS fonctionnement 3.1.3), je reçois ceci:

AudioUnitSetProperty (kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input) returned error -10868 
AudioUnitSetProperty (kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output) returned error -10868 

(-10868 est la valeur Je n'ai trouvé rien de valeur dans la documentation d'Apple, à l'exception d'un recommendation pour coller à des entiers little-endian 16 bits. Toutefois, le projet exemple aurioTouch contient au moins un code de support lié à kAudioFormatFlagIsFloat.

Alors, est-ce que ma description de flux est incorrecte, ou est-ce que kAudioFormatFlagIsFloat n'est pas supporté sur iPhoneOS?

Répondre

1

De la documentation Core Audio:

kAudioFormatFlagIsFloat 
    Set for floating point, clear for integer. 
    Available in iPhone OS 2.0 and later. 
    Declared in CoreAudioTypes.h. 

Je ne sais pas assez sur votre flux de commenter l'exactitude [en].

2

Ce n'est pas supporté, pour autant que je sache. Vous peut facilement convertir en flotteurs, mais en utilisant AudioConverter. Je fais cette conversion (bidirectionnelle) en temps réel pour utiliser le framework Accelerate avec l'audio iOS. (note: ce code est copié et collé à partir d'un code plus modulaire, donc il peut y avoir quelques fautes de frappe mineures)

D'abord, vous aurez besoin de la description audioStreamBasicDescription de l'entrée. Dites

AudioStreamBasicDescription aBasicDescription = {0}; 
aBasicDescription.mSampleRate  = self.samplerate; 
aBasicDescription.mFormatID   = kAudioFormatLinearPCM; 
aBasicDescription.mFormatFlags  = kAudioFormatFlagIsSignedInteger |  kAudioFormatFlagIsPacked; 
aBasicDescription.mFramesPerPacket   = 1; 
aBasicDescription.mChannelsPerFrame  = 1; 
aBasicDescription.mBitsPerChannel  = 8 * sizeof(SInt16); 
aBasicDescription.mBytesPerPacket  = sizeof(SInt16) * aBasicDescription.mFramesPerPacket; 
aBasicDescription.mBytesPerFrame  = sizeof(SInt16) * aBasicDescription.mChannelsPerFrame 

Ensuite, générez une AudioStreamBasicDescription correspondante pour float.

AudioStreamBasicDescription floatDesc = {0}; 
floatDesc.mFormatID = kAudioFormatLinearPCM;  
floatDesc.mFormatFlags = kAudioFormatFlagIsFloat | kAudioFormatFlagIsPacked; 
floatDesc.mBitsPerChannel = 8 * sizeof(float); 
floatDesc.mFramesPerPacket = 1;           
floatDesc.mChannelsPerFrame = 1;   
floatDesc.mBytesPerPacket = sizeof(float) * floatDesc.mFramesPerPacket;                    
floatDesc.mBytesPerFrame = sizeof(float) * floatDesc.mChannelsPerFrame;                     
floatDesc.mSampleRate = [controller samplerate]; 

Créer des tampons.

UInt32 intSize = inNumberFrames * sizeof(SInt16); 
UInt32 floatSize = inNumberFrames * sizeof(float); 
float *dataBuffer = (float *)calloc(numberOfAudioFramesIn, sizeof(float)); 

Puis convertir. (IODATA est votre AudioBufferList contenant l'audio int)

AudioConverterRef converter; 
OSStatus err = noErr; 
err = AudioConverterNew(&aBasicDescription, &floatDesct, &converter); 
//check for error here in "real" code 
err = AudioConverterConvertBuffer(converter, intSize, ioData->mBuffers[0].mData, &floatSize, dataBuffer); 
//check for error here in "real" code 
//do stuff to dataBuffer, which now contains floats 
//convert the floats back by running the conversion the other way 
1

Il est pris en charge. Le problème est que vous devez également définir kAudioFormatFlagIsNonInterleaved sur mFormatFlags. Si vous ne le faites pas lors du réglage kAudioFormatFlagIsFloat, vous obtiendrez une erreur de format.

Donc, vous voulez faire quelque chose comme ça lors de la préparation de votre AudioStreamBasicDescription:

streamDescription.mFormatFlags = kAudioFormatFlagIsFloat | 
           kAudioFormatFlagIsNonInterleaved; 

Quant à savoir pourquoi iOS exige, je ne suis pas sûr - je ne suis tombé sur elle par essais et erreurs.

1

Je fais quelque chose sans rapport avec AudioUnits mais j'utilise AudioStreamBasicDescription sur iOS. J'ai pu utiliser des échantillons de flotteur en spécifiant:

dstFormat.mFormatFlags = kAudioFormatFlagIsFloat | kAudioFormatFlagIsNonInterleaved | kAudioFormatFlagsNativeEndian | kLinearPCMFormatFlagIsPacked; 

Le livre Learning Core Audio: A Hands-on Guide to Audio Programming for Mac and iOS utile pour cela.