I play MIDI files on iPhone using MIKMIDISynthesizerfrom this library . Unfortunately, this level is very low, even when you fully increase the volume of the iPhone system. To increase it, I tried these things:
- change all MIDI note. The value of the event speed is not more than 127. This is a little, but not enough increase the volume.
- Add the node's mixer
AUGraphas described here . This boosts the volume enough, but instantly distorts the signal so poorly that the quality is too poor. - Turn up the volume of the soundfont sample using a soundfont editor like Polyphone. This has no tangible effect.
Now my options are running out. Is there any additional parameter or level (for example, AVAudioSessionor CoreMIDImaybe) that I skipped that provides the ability to adjust the volume / gain? Or MIDI commands that do the same?
Code snippets
1. Using a node mixer
This is the part MIKMIDISynthesizerthat I modified to manage the volume using the node mixer.
- (BOOL)setupAUGraph
{
AUGraph graph;
OSStatus err = 0;
if ((err = NewAUGraph(&graph))) {
NSLog(@"Unable to create AU graph: %@", @(err));
return NO;
}
AudioComponentDescription outputcd = {0};
outputcd.componentType = kAudioUnitType_Output;
outputcd.componentSubType = kAudioUnitSubType_RemoteIO;
outputcd.componentManufacturer = kAudioUnitManufacturer_Apple;
AUNode outputNode;
if ((err = AUGraphAddNode(graph, &outputcd, &outputNode))) {
NSLog(@"Unable to add ouptput node to graph: %@", @(err));
return NO;
}
AudioComponentDescription instrumentcd = self.componentDescription;
AUNode instrumentNode;
if ((err = AUGraphAddNode(graph, &instrumentcd, &instrumentNode))) {
NSLog(@"Unable to add instrument node to AU graph: %@", @(err));
return NO;
}
if ((err = AUGraphOpen(graph))) {
NSLog(@"Unable to open AU graph: %@", @(err));
return NO;
}
AudioUnit instrumentUnit;
if ((err = AUGraphNodeInfo(graph, instrumentNode, NULL, &instrumentUnit))) {
NSLog(@"Unable to get instrument AU unit: %@", @(err));
return NO;
}
AUNode mixerNode;
AudioComponentDescription cd = {};
cd.componentManufacturer = kAudioUnitManufacturer_Apple;
cd.componentType = kAudioUnitType_Mixer;
cd.componentSubType = kAudioUnitSubType_MultiChannelMixer;
if ((err = AUGraphAddNode(graph, &cd, &mixerNode))) {
NSLog(@"Unable to add mixer node to AU graph: %@", @(err));
return NO;
}
if ((err = AUGraphNodeInfo(graph, mixerNode, 0, &_mixerUnit))) {
NSLog(@"Unable to fetch mixer node reference from AU graph: %@", @(err));
return NO;
}
UInt32 busCount = 2;
err = AudioUnitSetProperty(_mixerUnit,
kAudioUnitProperty_ElementCount,
kAudioUnitScope_Input,
0,
&busCount,
sizeof (busCount)
);
if (err) {
NSLog(@"Unable to set mixer unit properties");
return NO;
}
if ((err = AUGraphConnectNodeInput(graph, instrumentNode, 0, mixerNode, 0))) {
NSLog(@"Unable to connect input node and mixer node: %@", @(err));
return NO;
}
if ((err = AUGraphConnectNodeInput(graph, mixerNode, 0, outputNode, 0))) {
NSLog(@"Unable to connect input node and mixer node: %@", @(err));
return NO;
}
if ((err = AUGraphInitialize(graph))) {
NSLog(@"Unable to initialize AU graph: %@", @(err));
return NO;
}
if ((err = AUGraphStart(graph))) {
NSLog(@"Unable to start AU graph: %@", @(err));
return NO;
}
self.graph = graph;
self.instrumentUnit = instrumentUnit;
return YES;
}
After setting up the node mixer, I can change the volume like this ( introduces cropping! ):
-(void) setVolume: (float) volume {
AudioUnitSetParameter(_mixerUnit, kMultiChannelMixerParam_Volume, kAudioUnitScope_Output, 0, volume, 0);
}
2. Change MIDI events
The second approach sets the property velocityfor each node On event to a maximum of 127. It increases the volume without any noise, but only to a certain level. The code is inside MIKMIDINoteEvent:
+ (MIKMIDINoteOnCommand *)noteOnCommandFromNoteEvent:(MIKMIDINoteEvent *)noteEvent clock:(MIKMIDIClock *)clock
{
MIKMutableMIDINoteOnCommand *noteOn = [MIKMutableMIDINoteOnCommand commandForCommandType:MIKMIDICommandTypeNoteOn];
noteOn.midiTimestamp = [clock midiTimeStampForMusicTimeStamp:noteEvent.timeStamp];
noteOn.channel = noteEvent.channel;
noteOn.note = noteEvent.note;
noteOn.velocity = 127;
return [noteOn copy];
}