Domanda

Sto cercando un modo per mescolare 2 o più file MIDI, ciascuno con i propri file del carattere audio.Ho trovato il seguente codice per un file e ho provato a fare più giocatori di musica, ma immagino che non dovrebbe essere l'approccio giusto.Inoltre ottengo un po 'di spigolo strano ogni secondo.

Così c'è qualche altro modo, forse senza i metodi musicografici e musicalizzatori, utilizzando solo unità AU?

Ecco il codice che ho trovato in un altro filo:

-(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);
}
.

È stato utile?

Soluzione

Più istanze MusicPlayer suona un po 'imbarazzante (per mantenersi in sincronia) e ho dubbi che più i riagrafi funzionino. Non l'ho provato da solo.

Un approccio utilizzando un'istanza esclusiva di MusicPlayer sarebbe quello di caricare le tracce da ciascun file MIDI in una sequenza "Master". È possibile assegnare un nodo ausampler (con un soundfont unico) a ciascuna traccia (MusicTrackSetDestNode) e collegarli tutti attraverso un AUMixer. Dovresti gestire i tempi da ciascun file MIDI (utilizzando MusicTrackNewExtendedTempoEvent) per assegnare tempi di file alle tracce pertinenti. Le tracce di muting + il volume della traccia è facilmente gestibile con la traccia o il livello del mixer.

Immagino molto dipende dalla natura dei file MIDI con cui stai lavorando. Fwiw - Ho fatto molte ricerche sulla riproduzione di file MIDI su iOS e non c'è niente disponibile che è così facile da usare come MusicPlayer. Tuttavia, il bass lib potrebbe valere la pena guardare se MusicPlayer risulta non funzionare per te.

Specifica del numero di ingressi del mixer:

// 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;}
.

Altri suggerimenti

Ho avuto esattamente lo stesso problema come te.Tutte le tracce giocano con il primo strumento del font audio.Ho seguito la tua soluzione ma non funziona all'inizio.Infine, risolto il problema.Come accennato, la sequenza delle funzioni chiamando è davvero materano.Sì.In realtà, la sequenza chiamando dovrebbe essere così:

.....
MusicSequenceSetAUGraph(s, _processingGraph);
.......
MusicTrackSetDestNode(track[i], samplerNodes[i]);
......
[self loadFromDLSOrSoundFont];
......
MusicPlayerStart(p);
.

funziona nel mio progetto.

Così ho provato a impostare i nodi per ogni traccia, ma ciò non ha cambiato nulla.Il SoundFont viene impostato solo per il primo samplerUnit. Ecco come ho impostato il grafico:

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);
.

Questo è il metodo di esempio da Pagine Developer Apple che ho modificato per assegnare un SoundFont a uno specifico 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;
}
.

Allora l'ho fatto due volte per ottenere ogni traccia in 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);
.

e infine:

MusicTrackSetDestNode(track, samplerNode);
MusicTrackSetDestNode(track2, samplerNode2);
.

Ma questo non assegnerà il SoundFont al samplerUnit2:

[self loadFromDLSOrSoundFont: (NSURL *)presetURL2 withPatch: (int)0 withAudioUnit:self.samplerUnit2];
.

Assegnazione a samplerUnit funziona bene.Qualche idea Che cosa mi manca qui?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top