collegamento di Davide Vosti per http://lists.apple.com/archives/coreaudio-api/2008/Dec/msg00173.html non funziona più, dal momento che le liste di Apple sembrano non rispondere. Ecco la cache di Google per completezza.
//
// 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
Questo non è corretto. Non dovresti chiamare AudioQueueCallback nel ciclo di allocazione. Non credo nemmeno che la descrizione sia corretta. Inoltre, dovresti chiamare AudioQueueStart (audioQueue, nil) invece di questo strano modo. Guarda invece AudioUnit Framework. – thefaj
@thefaj: credo che tu sia quello che non è corretto. Questo esempio è tratto dalla mia app SC68 Player (http://itunes.apple.com/se/app/sc68-player/id295290413?mt=8), dove in origine ho preso il codice per la riproduzione audio dall'app di iPhone di esempio di Apple SpeakHere (http://developer.apple.com/iphone/library/samplecode/SpeakHere/), guarda il file AQPlayer.mm. È disponibile il codice sorgente completo per il lettore SC68 (http://www.peylow.se/sc68player.html). – PeyloW
Nell'esempio manca AudioQueueStart(), che deve essere chiamato AudioQueueCallback. – thefaj