ios - 如何在 iOS 上增加 MIDI 合成器音量/增益而不失真?

标签 ios objective-c iphone core-audio midi

我正在使用来自 this libraryMIKMIDISynthesizer 在 iPhone 上播放 MIDI 文件.不幸的是,音量非常低,即使将 iPhone 的系统音量调到最大也是如此。为了进一步增加它,我尝试了这些东西:

  • 将所有 MIDI Note On 事件的速度属性修改为最大值 127。这会轻微但不足以提高音量。
  • 混合器节点添加到AUGraph,如所述here .这足以提高音量,但会立即严重扭曲信号,以至于质量太差。
  • 使用 Polyphone 等音色编辑器提高音色样本的音量。这没有明显的效果。

现在我的选项用完了。是否有我错过的任何其他参数或级别(例如 AVAudioSessionCoreMIDI)并提供了调整音量/增益的可能性?还是执行相同操作的 MIDI 命令?


代码片段

<强>1。使用混合器节点

这是我修改的 MIKMIDISynthesizer 部分,以便使用混音器节点控制音量。

- (BOOL)setupAUGraph
{
    AUGraph graph;
    OSStatus err = 0;

    // 1. Create new AUGraph
    if ((err = NewAUGraph(&graph))) {
        NSLog(@"Unable to create AU graph: %@", @(err));
        return NO;
    }

    // 2. Create output node
    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;
    }

    // 3. Create the instrument node
    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;
    }

    // 4. Create the mixer node
    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;
    }

    // 5.1 Connect the instrument node as the mixer node's input
    if ((err = AUGraphConnectNodeInput(graph, instrumentNode, 0, mixerNode, 0))) {
        NSLog(@"Unable to connect input node and mixer node: %@", @(err));
        return NO;
    }

    // 5.2 Connect the mixer node as the output node's input
    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;
    }

    // 6. Finally, start the graph
    if ((err = AUGraphStart(graph))) {
        NSLog(@"Unable to start AU graph: %@", @(err));
        return NO;
    }

    self.graph = graph;
    self.instrumentUnit = instrumentUnit;

    return YES;
}

设置混音器节点后,我可以像这样改变音量(引入剪辑!):

-(void) setVolume: (float) volume {
    AudioUnitSetParameter(_mixerUnit, kMultiChannelMixerParam_Volume, kAudioUnitScope_Output, 0, volume, 0);
}

<强>2。更改 MIDI 事件

第二种方法将每个 Node On 事件的 velocity 属性设置为最大值 127。它会在没有任何噪音的情况下增加音量,但只会增加到一定程度。代码位于 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; // <------- Here's the magic
    return [noteOn copy];
}

最佳答案

MIDI 合成器使用的某些类型的采样波形可能会发生这种情况。采样波形的峰值音量可能已经包含接近或处于该格式可能的最大值的样本(例如,对于 16 位样本为 +-32767,对于浮点样本为 +-1.0),即使平均音量(能量总和)是太低。因此,任何简单的音量线性增加都会产生听起来很糟糕的削波噪声。

各种压缩器技术或滤波器可能能够在不削波的情况下增加平均音量,但这可以增加其自身的质量降低(但比削波更不烦人)失真。

补充:使用另一个 midi 采样器、声音字体或具有接近恒定音量(较低的 PAPR、峰均功率比)的声音是另一种可能性。

关于ios - 如何在 iOS 上增加 MIDI 合成器音量/增益而不失真?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35540721/

相关文章:

ios - NSDataDetector 类型 NSTextCheckingTypeTransitInformation - 它可用于 iOS 吗?

objective-c - pod 内的供应商框架无法被项目或其他 pod 识别(Cocoapods/Cocoapods #3810)

objective-c - MKMapView 平移导致父 UIScrollView 滚动

iphone - 防止在越狱设备上购买假冒应用程序

ios - 我试图在我的 ViewController 上放置多个 UICollectionView,但只有一个 UICollectionView 在模拟上运行

ios - UIButton 没有响应触摸

ios - Sprite Kit 碰撞次数超过 1 次

ios - NSMutableArray 对副本的更改也会导致父 NSMutableArray 的更改

ios - StoryBoard IOS 中的双 TabBar

iphone - 如何将项目从 Documents 目录复制到 iPhone App 中的 .app 目录?