gpt4 book ai didi

ios - 为什么我的多 channel 混音器在 iOS 8 中不再播放?

转载 作者:行者123 更新时间:2023-11-29 02:23:59 24 4
gpt4 key购买 nike

我编写了一些代码来在 iOS 上播放多乐器通用 MIDI 文件。它在 iOS 7 上运行良好,但在 iOS 8 上停止运行。

我在这里将其剥离到其本质。我没有为多 channel 混音器创建 16 个 channel ,而是仅创建一个采样器节点,并将所有轨道映射到该 channel 。它仍然存在与多采样器版本相同的问题。在 iOS 7 或 iOS 8 中,所有音频工具箱调用都不会返回错误代码(它们都返回 0)。该序列通过 iOS 7 中的扬声器在模拟器和 iPhone/iPad 设备上播放。在 iOS 8 模拟器或 iPhone/iPad 设备上运行完全相同的代码,不会产生任何声音。

如果您注释掉对 [self initGraphFromMIDISequence] 的调用,它会在 iOS 8 上以默认的正弦波声音播放。

@implementation MyMusicPlayer {
MusicPlayer _musicPlayer;
MusicSequence _musicSequence;
AUGraph _processingGraph;
}

- (void)playMidi:(NSURL*)midiFileURL {
NewMusicSequence(&_musicSequence);
MusicSequenceFileLoad(_musicSequence, CFBridgingRetain(midiFileURL), 0, 0);

NewMusicPlayer(&_musicPlayer);
MusicPlayerSetSequence(_musicPlayer, _musicSequence);

[self initGraphFromMIDISequence];

MusicPlayerPreroll(_musicPlayer);
MusicPlayerStart(_musicPlayer);
}

// Sets up an AUGraph with one channel whose instrument is loaded from a sound bank.
// Maps all the tracks of the MIDI sequence onto that channel. Basically this is a
// way to replace the default sine-wave sound with another (single) instrument.
- (void)initGraphFromMIDISequence {
NewAUGraph(&_processingGraph);

// Add one sampler unit to the graph.
AUNode samplerNode;
AudioComponentDescription cd = {};
cd.componentManufacturer = kAudioUnitManufacturer_Apple;
cd.componentType = kAudioUnitType_MusicDevice;
cd.componentSubType = kAudioUnitSubType_Sampler;
AUGraphAddNode(_processingGraph, &cd, &samplerNode);

// Add a Mixer unit node to the graph
cd.componentType = kAudioUnitType_Mixer;
cd.componentSubType = kAudioUnitSubType_MultiChannelMixer;
AUNode mixerNode;
AUGraphAddNode(_processingGraph, &cd, &mixerNode);

// Add the Output unit node to the graph
cd.componentType = kAudioUnitType_Output;
cd.componentSubType = kAudioUnitSubType_RemoteIO; // Output to speakers.
AUNode ioNode;
AUGraphAddNode(_processingGraph, &cd, &ioNode);

AUGraphOpen(_processingGraph);

// Obtain the mixer unit instance from its corresponding node, and set the bus count to 1.
AudioUnit mixerUnit;
AUGraphNodeInfo(_processingGraph, mixerNode, NULL, &mixerUnit);
UInt32 const numChannels = 1;
AudioUnitSetProperty(mixerUnit,
kAudioUnitProperty_ElementCount,
kAudioUnitScope_Input,
0,
&numChannels,
sizeof(numChannels));

// Connect the sampler node's output 0 to mixer node output 0.
AUGraphConnectNodeInput(_processingGraph, samplerNode, 0, mixerNode, 0);

// Connect the mixer unit to the output unit.
AUGraphConnectNodeInput(_processingGraph, mixerNode, 0, ioNode, 0);

// Obtain reference to the audio unit from its node.
AudioUnit samplerUnit;
AUGraphNodeInfo(_processingGraph, samplerNode, 0, &samplerUnit);
MusicSequenceSetAUGraph(_musicSequence, _processingGraph);

// Set the destination for each track to our single sampler node.
UInt32 trackCount;
MusicSequenceGetTrackCount(_musicSequence, &trackCount);
MusicTrack track;
for (int i = 0; i < trackCount; i++) {
MusicSequenceGetIndTrack(_musicSequence, i, &track);
MusicTrackSetDestNode(track, samplerNode);
}

// You can use either a DLS or an SF2 file bundled with your app; both work in iOS 7.
//NSString *soundBankPath = [[NSBundle mainBundle] pathForResource:@"GeneralUserv1.44" ofType:@"sf2"];
NSString *soundBankPath = [[NSBundle mainBundle] pathForResource:@"gs_instruments" ofType:@"dls"];
NSURL *bankURL = [NSURL fileURLWithPath:soundBankPath];
AUSamplerBankPresetData bpdata;
bpdata.bankURL = (__bridge CFURLRef) bankURL;
bpdata.bankMSB = kAUSampler_DefaultMelodicBankMSB;
bpdata.bankLSB = kAUSampler_DefaultBankLSB;
bpdata.presetID = 0;
UInt8 instrumentNumber = 46; // pick any GM instrument 0-127
bpdata.presetID = instrumentNumber;
AudioUnitSetProperty(samplerUnit,
kAUSamplerProperty_LoadPresetFromBank,
kAudioUnitScope_Global,
0,
&bpdata,
sizeof(bpdata));
}

我有一些代码(此处未包含),通过在 MusicPlayer 实例上调用 MusicPlayerGetTime 来轮询序列是否仍在播放。在 iOS 7 中,每次调用的结果是自开始播放以来经过的秒数。在 iOS 8 中,调用始终返回 0,这可能意味着 MusicPlayer 不会在调用 MusicPlayerStart 时开始播放序列。

上面的代码高度依赖于顺序——您必须在其他调用之前进行某些调用;例如,在节点上调用 getInfo 之前打开图表,并且在将轨道分配给 channel 之前不加载乐器。我已遵循其他 StackOverflow 线程中的所有建议,并已验证正确的顺序会使错误代码消失。

任何 iOS MIDI 专家都知道 iOS 7 和 iOS 8 之间可能发生了什么变化,导致此代码停止工作吗?

最佳答案

在 iOS 8 中,Apple 引入了一个巧妙的 Obj-C 核心音频 API 抽象 - AVAudioEngine。你应该检查一下。 https://developer.apple.com/videos/wwdc/2014/#502

关于ios - 为什么我的多 channel 混音器在 iOS 8 中不再播放?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27772680/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com