ios - 각각 고유한 사운드 글꼴이 있는 미디 파일 믹싱
-
13-12-2019 - |
문제
각각 고유한 사운드 글꼴 파일이 있는 2개 이상의 미디 파일을 혼합하는 방법을 찾고 있습니다.하나의 파일에 대해 다음 코드를 찾았고 여러 음악 플레이어를 시도했지만 올바른 접근 방식은 아닌 것 같습니다.또한 매초마다 이상한 팝 사운드가 들립니다.
그렇다면 musicplayer와 musicsequence 메서드 없이 au 단위만 사용하는 다른 방법이 있을까요?
다른 스레드에서 찾은 코드는 다음과 같습니다.
-(void) playMusic:(NSString*) name
{
NSString *presetURLPath = [[NSBundle mainBundle] pathForResource:@"GortsMiniPianoJ1" ofType:@"SF2"];
NSURL * presetURL = [NSURL fileURLWithPath:presetURLPath];
[self loadFromDLSOrSoundFont: (NSURL *)presetURL withPatch: (int)3];
NSString *midiFilePath = [[NSBundle mainBundle] pathForResource:name ofType:@"mid"];
NSURL * midiFileURL = [NSURL fileURLWithPath:midiFilePath];
NewMusicPlayer(&musicPlayer);
if (NewMusicSequence(&musicSequence) != noErr)
{
[NSException raise:@"play" format:@"Can't create MusicSequence"];
}
if(MusicSequenceFileLoad(musicSequence, (CFURLRef)midiFileURL, 0, 0 != noErr))
{
[NSException raise:@"play" format:@"Can't load MusicSequence"];
}
MusicPlayerSetSequence(musicPlayer, musicSequence);
MusicSequenceSetAUGraph(musicSequence, _processingGraph);
MusicPlayerPreroll(musicPlayer);
MusicPlayerStart(musicPlayer);
}
해결책
여러 개의 MusicPlayer 인스턴스가 동기화를 유지하기에는 다소 어색한 것처럼 들리며 여러 개의 AUGraph가 작동할지 의심스럽습니다.나는 그것을 직접 시도하지 않았습니다.
단일 인스턴스를 사용하는 한 가지 접근 방식 MusicPlayer
각 미디 파일의 트랙을 '마스터' 시퀀스로 로드하는 것입니다.AUSampler 노드(고유한 soundFont 포함)를 각 트랙에 할당할 수 있습니다(MusicTrackSetDestNode
) 그리고 이를 모두 통해 연결합니다. AUMixer
.각 미디 파일의 템포를 관리해야 합니다(다음을 사용). MusicTrackNewExtendedTempoEvent
) 관련 트랙에 파일 템포를 할당합니다.트랙 음소거 + 트랙 볼륨은 트랙 또는 믹서 수준에서 쉽게 처리됩니다.
작업 중인 미디 파일의 특성에 따라 많은 부분이 달라질 것 같습니다.Fwiw - 저는 iOS에서 미디 파일 재생에 대해 많은 연구를 했는데 MusicPlayer만큼 사용하기 쉬운 것은 없습니다.그러나, 그 베이스 라이브러리 MusicPlayer가 귀하에게 적합하지 않은 것으로 판명되면 살펴볼 가치가 있습니다.
믹서 입력 수 지정:
// set the bus count
UInt32 numBuses = BUS_COUNT; // a constant defined elsewhere
result = AudioUnitSetProperty(mixerUnit,
kAudioUnitProperty_ElementCount,
kAudioUnitScope_Input,
0,
&numBuses,
sizeof(numBuses));
if (noErr != result) {[self printErrorMessage: @"Error setting Bus Count" withStatus: result]; return;}
다른 팁
나는 당신과 똑같은 문제가있었습니다.모든 트랙은 첫 번째 사운드 글꼴 악기로 재생됩니다.나는 당신의 솔루션을 따라 갔지만 처음에는 작동하지 않습니다.마지막으로 문제를 해결합니다.언급 한 것처럼, 호출하는 일련은 실제로 매숙합니다.네, 그렇습니다.사실, 순서 호출은 다음과 같아야합니다.
.....
MusicSequenceSetAUGraph(s, _processingGraph);
.......
MusicTrackSetDestNode(track[i], samplerNodes[i]);
......
[self loadFromDLSOrSoundFont];
......
MusicPlayerStart(p);
.
이 프로젝트에서 작동합니다.
그래서 각 트랙의 노드를 설정해 보았지만 아무 것도 바뀌지 않았습니다.사운드 폰트는 첫 번째에만 설정됩니다. samplerUnit
.그래프를 설정하는 방법은 다음과 같습니다.
AudioComponentDescription MixerUnitDescription;
MixerUnitDescription.componentType = kAudioUnitType_Mixer;
MixerUnitDescription.componentSubType = kAudioUnitSubType_MultiChannelMixer;
MixerUnitDescription.componentManufacturer = kAudioUnitManufacturer_Apple;
MixerUnitDescription.componentFlags = 0;
MixerUnitDescription.componentFlagsMask = 0;
AudioComponentDescription cd = {};
cd.componentManufacturer = kAudioUnitManufacturer_Apple;
cd.componentType = kAudioUnitType_MusicDevice; // type - music device
cd.componentSubType = kAudioUnitSubType_Sampler; // sub type - sampler to convert our MIDI
result = NewAUGraph (&_processingGraph);
result = AUGraphAddNode(self.processingGraph, &MixerUnitDescription, &mixerNode);
result = AUGraphAddNode (self.processingGraph, &cd, &samplerNode);
result = AUGraphAddNode (self.processingGraph, &cd, &samplerNode2);
cd.componentType = kAudioUnitType_Output; // Output
cd.componentSubType = kAudioUnitSubType_RemoteIO; // Output to speakers
result = AUGraphAddNode (self.processingGraph, &cd, &ioNode);
result = AUGraphOpen (self.processingGraph);
result = AUGraphConnectNodeInput (self.processingGraph, samplerNode, 0, mixerNode, 0);
result = AUGraphConnectNodeInput (self.processingGraph, samplerNode2, 0, mixerNode, 1);
result = AUGraphConnectNodeInput (self.processingGraph, mixerNode, 0, ioNode, 0);
result = AUGraphNodeInfo (self.processingGraph, samplerNode, 0, &_samplerUnit);
result = AUGraphNodeInfo (self.processingGraph, samplerNode2, 0, &_samplerUnit2);
result = AUGraphNodeInfo (self.processingGraph, ioNode, 0, &_ioUnit);
이것은 특정 사운드 글꼴에 사운드 글꼴을 할당하기 위해 수정한 Apple 개발자 페이지의 예제 방법입니다. samplerUnit
:
-(OSStatus) loadFromDLSOrSoundFont: (NSURL *)bankURL withPatch: (int)presetNumber withAudioUnit:(AudioUnit)auUnit{
OSStatus result = noErr;
// fill out a bank preset data structure
AUSamplerBankPresetData bpdata;
bpdata.bankURL = (__bridge CFURLRef) bankURL;
bpdata.bankMSB = kAUSampler_DefaultMelodicBankMSB;
bpdata.bankLSB = kAUSampler_DefaultBankLSB;
bpdata.presetID = (UInt8) presetNumber;
// set the kAUSamplerProperty_LoadPresetFromBank property
result = AudioUnitSetProperty(auUnit,
kAUSamplerProperty_LoadPresetFromBank,
kAudioUnitScope_Global,
0,
&bpdata,
sizeof(bpdata));
// check for errors
NSCAssert (result == noErr,
@"Unable to set the preset property on the Sampler. Error code:%d '%.4s'",
(int) result,
(const char *)&result);
return result;
}
그런 다음 각 트랙을 삽입하기 위해 이 작업을 두 번 수행했습니다. musicSequence
:
if(MusicSequenceFileLoad(tmpSequence, (__bridge CFURLRef)midiFileURL, 0, 0 != noErr))
{
[NSException raise:@"play" format:@"Can't load MusicSequence"];
}
MusicSequenceGetIndTrack(tmpSequence, 0, &tmpTrack);
MusicSequenceNewTrack(musicSequence, &track);
MusicTimeStamp trackLen = 0;
UInt32 trackLenLen = sizeof(trackLen);
MusicTrackGetProperty(tmpTrack, kSequenceTrackProperty_TrackLength, &trackLen, &trackLenLen);
MusicTrackCopyInsert(tmpTrack, 0, trackLenLen, track, 0);
그리고 마지막으로:
MusicTrackSetDestNode(track, samplerNode);
MusicTrackSetDestNode(track2, samplerNode2);
하지만 이렇게 하면 사운드 글꼴이 할당되지 않습니다. samplerUnit2
:
[self loadFromDLSOrSoundFont: (NSURL *)presetURL2 withPatch: (int)0 withAudioUnit:self.samplerUnit2];
할당 대상 samplerUnit
잘 작동합니다.내가 여기서 무엇을 놓치고 있는지 어떤 아이디어가 있습니까?