#include #include #include #include static void check (OSStatus err, const char* what) { if (err != noErr) printf ("FAIL: %s -> %d\n", what, (int) err); else printf ("PASS: %s\n", what); } int main (int argc, char** argv) { if (argc < 2) { printf ("usage: %s \n", argv[0]); return 2; } void* handle = dlopen (argv[1], RTLD_NOW | RTLD_LOCAL); if (!handle) { printf ("FAIL: dlopen -> %s\n", dlerror()); return 1; } printf ("PASS: dlopen bundle\n"); AudioComponentDescription desc; memset (&desc, 0, sizeof (desc)); desc.componentType = kAudioUnitType_Effect; desc.componentSubType = 'Pscp'; desc.componentManufacturer = 'PscC'; desc.componentFlags = 0; desc.componentFlagsMask = 0; void* (*factory) (const AudioComponentDescription*) = dlsym (handle, "PascalcompressorAUFactory"); if (!factory) { printf ("FAIL: dlsym factory -> %s\n", dlerror()); return 1; } printf ("PASS: dlsym factory\n"); AudioComponent comp = AudioComponentRegister (&desc, CFSTR ("Pascal: Pascalcompressor"), 0x00010000, (AudioComponentFactoryFunction) factory); if (!comp) { printf ("FAIL: AudioComponentRegister\n"); return 1; } printf ("PASS: AudioComponentRegister\n"); AudioUnit au = 0; check (AudioComponentInstanceNew (comp, &au), "AudioComponentInstanceNew"); if (!au) return 1; printf (" instance %p\n", (void*) au); AudioUnitParameterInfo info; memset (&info, 0, sizeof (info)); UInt32 infoSz = sizeof (info); for (UInt32 pid = 0; pid < 7; ++pid) { if (AudioUnitGetProperty (au, kAudioUnitProperty_ParameterInfo, kAudioUnitScope_Global, pid, &info, &infoSz) == noErr) printf (" parameter %u: default %.3f name='%s'\n", (unsigned) pid, (double) info.defaultValue, info.cfNameString ? CFStringGetCStringPtr (info.cfNameString, kCFStringEncodingUTF8) : "?"); } AudioStreamBasicDescription fmt; memset (&fmt, 0, sizeof (fmt)); fmt.mSampleRate = 44100.0; fmt.mFormatID = kAudioFormatLinearPCM; fmt.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kAudioFormatFlagIsNonInterleaved; fmt.mBytesPerPacket = 4; fmt.mFramesPerPacket = 1; fmt.mBytesPerFrame = 4; fmt.mChannelsPerFrame = 2; fmt.mBitsPerChannel = 32; check (AudioUnitSetProperty (au, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &fmt, sizeof (fmt)), "Set input format"); check (AudioUnitSetProperty (au, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &fmt, sizeof (fmt)), "Set output format"); check (AudioUnitInitialize (au), "AudioUnitInitialize"); AudioUnitParameter p; memset (&p, 0, sizeof (p)); p.mAudioUnit = au; for (int i = 0; i < 7; ++i) { p.mParameterID = (AudioUnitParameterID) i; p.mScope = kAudioUnitScope_Global; p.mElement = 0; AudioUnitParameterValue value = 0.0f; OSStatus err = AudioUnitGetParameter (au, p.mParameterID, p.mScope, p.mElement, &value); if (err == noErr) printf (" parameter %d = %.3f\n", i, (double) value); } AudioUnitParameterValue setTo = 0.5f; check (AudioUnitSetParameter (au, 1, kAudioUnitScope_Global, 0, setTo, 0), "Set threshold parameter"); const int numFrames = 512; AudioBufferList abl; abl.mNumberBuffers = 2; for (int c = 0; c < 2; ++c) { abl.mBuffers[c].mNumberChannels = 1; abl.mBuffers[c].mDataByteSize = numFrames * sizeof (float); abl.mBuffers[c].mData = malloc (abl.mBuffers[c].mDataByteSize); memset (abl.mBuffers[c].mData, 0, abl.mBuffers[c].mDataByteSize); } AudioTimeStamp ts; memset (&ts, 0, sizeof (ts)); ts.mSampleTime = 0.0; ts.mFlags = kAudioTimeStampSampleTimeValid; check (AudioUnitRender (au, NULL, &ts, 0, numFrames, &abl), "AudioUnitRender (silence)"); float* ch0 = (float*) abl.mBuffers[0].mData; float peak = 0.0f; for (int n = 0; n < numFrames; ++n) peak = peak > ch0[n] ? peak : ch0[n]; printf (" rendered peak: %.6f\n", (double) peak); for (int c = 0; c < 2; ++c) free (abl.mBuffers[c].mData); check (AudioComponentInstanceDispose (au), "AudioComponentInstanceDispose"); dlclose (handle); return 0; }