• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
AUGraph tone-generator having trouble with some sound fonts, but not others
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

AUGraph tone-generator having trouble with some sound fonts, but not others


  • Subject: AUGraph tone-generator having trouble with some sound fonts, but not others
  • From: Frank Weinstock <email@hidden>
  • Date: Thu, 18 Dec 2014 09:26:34 -0500

Good morning, collective wisdom!

I have written an iOS 16-channel General MIDI tone generator using an AUGraph, and it works great with some DLSs and sound fonts, and sounds terrible with others. With some DLSs and sound fonts, I can play a sequence and get essentially the same sound as I hear from other iOS apps (e.g. bs-16i) playing the same sequence and using the same DLS or sound font; but with DLSs or sound fonts, I get a much worse sound quality than from the other app, notes that don't sound, etc.--not even close to acceptable. It's particularly surprising since the difference in quality exists only for some DLSs and sound fonts--so what I'm doing works for some, but is not sufficient for others.

Below is the function newAUGraph(), which creates an AUGraph consisting of 16 AUSamplers (one for each channel), each with an output to a mixer, which combines the 16 channels and routes them to a reverb unit, which then sends the sounds to the output unit; the AUGraph and the sixteen AUSamplers are stored in the external (global) variables auGraph and auSampler[16].  Presets are subsequently loaded into each channel's AUSampler, and notes and other MIDI messages are sent via MusicDeviceMIDIEvent().

If anybody has time to slog through this and give me a hint as to what I'm missing, I'll be forever grateful.  In any case, thanks for your attention!

All best,
Frank


****************

AUGraph auGraph;
AudioUnit auSampler[16];

#define mustHaveNoError(functionCall) functionCall; if (result != noErr) {NSLog (@"error %d", (int)result); return result;}

static OSStatus newAUGraph (void)
{
AudioUnit mixerAudioUnit, reverbAudioUnit, outputAudioUnit;
AUNode samplerNode[16], mixerNode, reverbNode, outputNode;


AVAudioSession* avAudioSession = [AVAudioSession sharedInstance];

[avAudioSession setCategory: AVAudioSessionCategoryPlayback error: nil];
[avAudioSession setPreferredHardwareSampleRate:44100.0 error:nil];
[avAudioSession setActive:YES error:nil];
Float64 sampleRate = avAudioSession.currentHardwareSampleRate;


AudioComponentDescription description;

description.componentManufacturer = kAudioUnitManufacturer_Apple;
description.componentFlags = description.componentFlagsMask = 0;


OSStatus result = mustHaveNoError(NewAUGraph(&auGraph));


description.componentType = kAudioUnitType_Output;

description.componentSubType = kAudioUnitSubType_RemoteIO;
result = mustHaveNoError(AUGraphAddNode (auGraph, &description, &outputNode));


description.componentType = kAudioUnitType_Effect;

description.componentSubType = kAudioUnitSubType_Reverb2;
result = mustHaveNoError(AUGraphAddNode (auGraph, &description, &reverbNode));


description.componentType = kAudioUnitType_Mixer;

description.componentSubType = kAudioUnitSubType_MultiChannelMixer;
result = mustHaveNoError(AUGraphAddNode (auGraph, &description, &mixerNode));


result = mustHaveNoError(AUGraphConnectNodeInput(auGraph, reverbNode, 0, outputNode, 0));

result = mustHaveNoError(AUGraphConnectNodeInput(auGraph, mixerNode, 0, reverbNode, 0));


const UInt32 numberOfChannels = 16;

for (unsigned int i = 0; i < numberOfChannels; i += 1)
{
description.componentType = kAudioUnitType_MusicDevice;
description.componentSubType = kAudioUnitSubType_Sampler;
result = mustHaveNoError(AUGraphAddNode (auGraph, &description, &samplerNode[i]));
result = mustHaveNoError(AUGraphConnectNodeInput(auGraph, samplerNode[i], 0, mixerNode, i));
}


result = mustHaveNoError(AUGraphOpen (auGraph));


result = mustHaveNoError(AUGraphNodeInfo(auGraph, mixerNode, NULL, &mixerAudioUnit));

result = mustHaveNoError(AUGraphNodeInfo(auGraph, reverbNode, NULL, &reverbAudioUnit));
result = mustHaveNoError(AUGraphNodeInfo(auGraph, outputNode, NULL, &outputAudioUnit));


UInt32 framesPerSlice;

UInt32 framesPerSlicePropertySize = sizeof(framesPerSlice);
result = mustHaveNoError(AudioUnitGetProperty(outputAudioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &framesPerSlice, &framesPerSlicePropertySize));
assert(framesPerSlicePropertySize == sizeof(framesPerSlice));


result = mustHaveNoError(AudioUnitInitialize(outputAudioUnit));

result = mustHaveNoError(AudioUnitSetProperty(outputAudioUnit, kAudioUnitProperty_SampleRate, kAudioUnitScope_Output, 0, &sampleRate, sizeof(sampleRate)));
result = mustHaveNoError(AudioUnitSetProperty(outputAudioUnit, kAudioUnitProperty_SampleRate, kAudioUnitScope_Input, 0, &sampleRate, sizeof(sampleRate)));
result = mustHaveNoError(AudioUnitSetProperty(reverbAudioUnit, kAudioUnitProperty_SampleRate, kAudioUnitScope_Output, 0, &sampleRate, sizeof(sampleRate)));
result = mustHaveNoError(AudioUnitSetProperty(reverbAudioUnit, kAudioUnitProperty_SampleRate, kAudioUnitScope_Input, 0, &sampleRate, sizeof(sampleRate)));
result = mustHaveNoError(AudioUnitSetProperty(reverbAudioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &framesPerSlice, sizeof(framesPerSlice)));
result = mustHaveNoError(AudioUnitSetProperty(mixerAudioUnit, kAudioUnitProperty_SampleRate, kAudioUnitScope_Output, 0, &sampleRate, sizeof(sampleRate)));
result = mustHaveNoError(AudioUnitSetProperty(mixerAudioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &framesPerSlice, sizeof(framesPerSlice)));


result = mustHaveNoError(AudioUnitSetProperty(mixerAudioUnit, kAudioUnitProperty_ElementCount, kAudioUnitScope_Input, 0, &numberOfChannels, sizeof(numberOfChannels)));


result = mustHaveNoError(AudioUnitSetParameter(reverbAudioUnit, kReverb2Param_DryWetMix, kAudioUnitScope_Global, 0, 20, 0));

result = mustHaveNoError(AudioUnitSetParameter(reverbAudioUnit, kReverb2Param_DecayTimeAt0Hz, kAudioUnitScope_Global, 0, 3, 0));
result = mustHaveNoError(AudioUnitSetParameter(reverbAudioUnit, kReverb2Param_DecayTimeAtNyquist, kAudioUnitScope_Global, 0, 1, 0));


for (unsigned int i = 0; i < numberOfChannels; i += 1)

{
result = mustHaveNoError(AUGraphNodeInfo(auGraph, samplerNode[i], NULL, &auSampler[i]));
result = mustHaveNoError(AudioUnitSetProperty(auSampler[i], kAudioUnitProperty_SampleRate, kAudioUnitScope_Output, 0, &sampleRate, sizeof(sampleRate)));
result = mustHaveNoError(AudioUnitSetProperty(auSampler[i], kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &framesPerSlice, sizeof(framesPerSlice)));
result = mustHaveNoError(AudioUnitSetProperty(mixerAudioUnit, kAudioUnitProperty_SampleRate, kAudioUnitScope_Input, i, &sampleRate, sizeof(sampleRate)));
result = mustHaveNoError(AudioUnitSetProperty(mixerAudioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, i, &framesPerSlice, sizeof(framesPerSlice)));
result = mustHaveNoError(loadOnBoardSynthPatch(0, i));
result = mustHaveNoError(AudioUnitSetParameter(mixerAudioUnit, kMultiChannelMixerParam_Volume, kAudioUnitScope_Input, i, 1, 0));
}


result = mustHaveNoError(AUGraphInitialize(auGraph));

result = mustHaveNoError(AUGraphStart(auGraph));


CAShow(auGraph);

return result;
}


****************

Frank Weinstock
Professor Emeritus of Piano
College-Conservatory of Music
University of Cincinnati
email@hidden





 _______________________________________________
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

  • Prev by Date: How to use srcConnRefCon in MIDIReadProc function.
  • Next by Date: How to use srcConnRefCon in MIDIReadProc function.
  • Previous by thread: How to use srcConnRefCon in MIDIReadProc function.
  • Next by thread: Re: Coreaudio-api Digest, Vol 11, Issue 237
  • Index(es):
    • Date
    • Thread