Re: Monitoring input level
Re: Monitoring input level
- Subject: Re: Monitoring input level
- From: Neil Clayton <email@hidden>
- Date: Tue, 20 Jun 2006 00:33:22 +0100
Thanks for the tips.
I've written a spike, according to the link you mentioned.
I can get it to all start up OK (that is, no errors), but I'm not
getting anything for my levels. Just 'infinity'.
I (perhaps wrongly) didn't setup a channel map (hoping the default is
OK), or an input proc (as I don't want to actually DO anything with
the data).
Is an input proc required, even if I'm not wanting to save/play the
audio?
In the interest of keeping one thread only: Karim Morsy also replied
with the idea that I might be able to setup a link from AUHAL (input)
-> mixer -> AUHAL (output), but the docs say that you can only have
one output unit in a graph. I tried to create another unit using the
same component description, but got error -10862 (which I cannot see
doco for).
I've posted the code below, for reference. Hope it's not too much to
wade through. If you're looking for where I start things rolling,
it's at a method called monitorDevice.
---
Neil Clayton
//
// AudioPreview.m
// iShowU
//
// Created by Neil Clayton on 18/06/2006.
// Copyright 2006 __MyCompanyName__. All rights reserved.
//
#import "AudioPreview.h"
#import "DebugMacros.h"
#import "NSUtils.h"
#import "AudioToolbox/AudioFormat.h"
#import <AudioUnit/AudioUnitParameters.h>
#import <AudioUnit/AudioUnitProperties.h>
#import "CAStreamBasicDescription.h"
#define checkErr( err) \
if(err) {\
OSStatus error = static_cast<OSStatus>(err);\
fprintf(stderr, "Error: %ld -> %s: %d\n", error,\
__FILE__, \
__LINE__\
);\
fflush(stdout);\
}
@implementation AudioPreview
- (id) init {
self = [super init];
return self;
}
- (void) dealloc {
[self stopPreview];
[super dealloc];
}
- (void) enableIO {
UInt32 enableIO;
//When using AudioUnitSetProperty the 4th parameter in the method
//refer to an AudioUnitElement. When using an AudioOutputUnit
//the input element will be '1' and the output element will be '0'.
enableIO = 1;
AudioUnitSetProperty(inputUnit,
kAudioOutputUnitProperty_EnableIO,
kAudioUnitScope_Input,
1, // input element
&enableIO,
sizeof(enableIO));
enableIO = 0;
AudioUnitSetProperty(inputUnit,
kAudioOutputUnitProperty_EnableIO,
kAudioUnitScope_Output,
0, //output element
&enableIO,
sizeof(enableIO));
}
- (void) createHALAU {
ComponentDescription desc;
desc.componentType = kAudioUnitType_Output;
desc.componentSubType = kAudioUnitSubType_HALOutput;
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
desc.componentFlags = 0;
desc.componentFlagsMask = 0;
OSStatus err = AUGraphNewNode(auGraph, &desc, 0, NULL, &inputNode);
checkErr(err);
// err = AUGraphNewNode(auGraph, &desc, 0, NULL, &outputNode);
// checkErr(err);
err = AUGraphGetNodeInfo(auGraph, inputNode, NULL, NULL, NULL,
&inputUnit);
checkErr(err);
}
- (void) createMixer {
OSStatus err = noErr;
ComponentDescription mixer;
mixer.componentType = kAudioUnitType_Mixer;
mixer.componentSubType = kAudioUnitSubType_MatrixMixer;
mixer.componentManufacturer = kAudioUnitManufacturer_Apple;
mixer.componentFlags = 0;
mixer.componentFlagsMask = 0;
err = AUGraphNewNode(auGraph, &mixer, 0, NULL, &mixerNode);
checkErr(err);
err = AUGraphGetNodeInfo(auGraph, mixerNode, NULL, NULL, NULL,
&mixerUnit);
checkErr(err);
}
- (void) connectAUs {
OSStatus err = AUGraphConnectNodeInput(auGraph, mixerNode, 0,
inputNode, 0);
checkErr(err);
err = AUGraphConnectNodeInput(auGraph, inputNode, 1, mixerNode, 0);
checkErr(err);
err = AUGraphUpdate(auGraph, NULL);
checkErr(err);
}
- (void) setDevice:(AudioDeviceID)deviceId {
UInt32 size;
OSStatus err = noErr;
size = sizeof(AudioDeviceID);
err = AudioUnitSetProperty(inputUnit,
kAudioOutputUnitProperty_CurrentDevice,
kAudioUnitScope_Global,
0,
&deviceId,
sizeof(deviceId));
checkErr(err);
// Setup the StreamFormat for element 1 - the input element
CAStreamBasicDescription DeviceFormat;
CAStreamBasicDescription DesiredFormat;
size = sizeof(CAStreamBasicDescription);
//Get the input device format
err = AudioUnitGetProperty (inputUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input,
1,
&DeviceFormat,
&size);
checkErr(err);
//set the desired format to the device's sample rate
DesiredFormat.mSampleRate = DeviceFormat.mSampleRate;
//set format to output scope
err = AudioUnitSetProperty(inputUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Output,
1,
&DesiredFormat,
sizeof(CAStreamBasicDescription));
checkErr(err);
}
- (void) enableMetering {
// turn on metering
UInt32 meteringMode = 1;
OSStatus err = AudioUnitSetProperty(mixerUnit,
kAudioUnitProperty_MeteringMode, kAudioUnitScope_Global, 0,
&meteringMode, sizeof(meteringMode) );
checkErr(err);
}
- (void) setVolumes {
// Not sure if I need to do this or not. It's had no effect so far,
but did within ComplexPlayThru (when I modified it to have a mixer)
// // Enable the mixer input's and output's
// OSStatus err = AudioUnitSetParameter(mixerUnit,
kMatrixMixerParam_Enable, kAudioUnitScope_Input, 0, 1, 0);
// checkErr(err);
// err = AudioUnitSetParameter(mixerUnit, kMatrixMixerParam_Enable,
kAudioUnitScope_Output, 0, 1, 0);
// checkErr(err);
//
// // Set global volume
// err = AudioUnitSetParameter(mixerUnit, kMatrixMixerParam_Volume,
kAudioUnitScope_Global, 0, 1, 0);
// checkErr(err);
//
// // Set master volume
// err = AudioUnitSetParameter(mixerUnit, kMatrixMixerParam_Volume,
kAudioUnitScope_Global, 0xFFFFFFFF, 1, 0);
// checkErr(err);
//
// // Set input and output volumes
// err = AudioUnitSetParameter(mixerUnit, kMatrixMixerParam_Volume,
kAudioUnitScope_Input, 1, 1, 0);
// checkErr(err);
// err = AudioUnitSetParameter(mixerUnit, kMatrixMixerParam_Volume,
kAudioUnitScope_Output, 0, 1, 0);
// checkErr(err);
}
- (void) monitorDevice:(MTCoreAudioDevice*)aDevice {
[self stopPreview];
NewAUGraph(&auGraph);
OSStatus err = AUGraphOpen(auGraph);
checkErr(err);
[self createHALAU];
[self createMixer];
[self connectAUs];
err = AUGraphInitialize(auGraph);
checkErr(err);
[self enableIO];
[self setDevice:[aDevice deviceID]];
[self setVolumes]; // doesn't do anything at present
[self enableMetering];
[self startPreview];
}
- (void)idleTimer:(NSTimer*)timer {
OSStatus err;
float amps[2];
err = AudioUnitGetParameter(mixerUnit,
kMatrixMixerParam_PostAveragePower, kAudioUnitScope_Input, 0, &s[0]);
checkErr(err);
err = AudioUnitGetParameter(mixerUnit,
kMatrixMixerParam_PostPeakHoldLevel, kAudioUnitScope_Input, 0, &s
[1]);
checkErr(err);
currentAmps = amps[0];
peakAmps = amps[1];
NSLog(@"Got average power %f and peak power %f", currentAmps,
peakAmps);
}
- (void) stopPreview {
if(previewTimer) {
[previewTimer invalidate];
[previewTimer release];
previewTimer = nil;
OSStatus err = AUGraphStop(auGraph);
if(err != noErr) {
[self log:@"Error stopping AU graph, %d", err];
}
}
}
- (void) startPreview {
if (previewTimer == nil) {
previewTimer = [[NSTimer alloc] initWithFireDate:[NSDate date]
interval:.05
target:self
selector:@selector(idleTimer:)
userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:previewTimer
forMode:NSDefaultRunLoopMode];
OSStatus err = AUGraphStart(auGraph);
if(err != noErr) {
[self log:@"Error starting AU graph, %d", err];
}
}
}
@end
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Coreaudio-api mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden