Pregunta

Estoy buscando una manera de mezclar 2 o más archivos midi, cada uno con su propia fuente de sonido de los archivos.He encontrado el siguiente código en un archivo y trató de hacer varios reproductores de música, pero supongo que ese no debe ser el enfoque correcto.También tengo algo de extraño sonido pop cada segundo.

Así es, hay alguna otra manera, quizás sin la musicplayer y musicsequence métodos, utilizando sólo au unidades?

Aquí está el código que he encontrado en otro hilo:

-(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);
}
¿Fue útil?

Solución

Varios MusicPlayer instancias suena un poco torpe (sincronizar) y tengo dudas de que varios AUGraphs iba a funcionar.No he probado a mí mismo.

Una aproximación mediante una única instancia de MusicPlayer sería cargar los tracks de cada archivo midi en un 'maestro' de la secuencia.Puede asignar un AUSampler nodo (con la única soundFont) para cada pista (MusicTrackSetDestNode) y conectarlos todos a través de un AUMixer.Usted necesita para manejar los tempos de cada archivo midi (utilizando MusicTrackNewExtendedTempoEvent) para asignar el archivo de los tempos en los temas relevantes.Cómo silenciar pistas + el volumen de la pista es fácilmente manejado en la pista o en el mezclador de nivel.

Supongo que depende mucho de la naturaleza de los archivos midi que usted está trabajando.Fwiw - hice un montón de investigación sobre la reproducción de archivos midi en iOS y no hay nada que sea tan fácil de usar como MusicPlayer.Sin embargo, la Bajo lib podría ser vale la pena mirar si MusicPlayer resulta que no trabajan para usted.

Especificar el número de entradas del mezclador:

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

Otros consejos

Tuve exactamente el mismo problema que tú.Todas las pistas juegan con el primer instrumento de fuente de sonido.Seguí tu solución pero no funciona al principio.Finalmente, resuelvo el problema.Como se mencionó, la secuencia de funciones de llamadas realmente se mata.Sí lo es.En realidad, la llamada de secuencia debe ser así:

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

Esto funciona en mi proyecto.

Así que traté de configuración de los nodos para cada pista, pero eso no cambia nada.El soundfont obtiene sólo de la primera samplerUnit.He aquí cómo puedo configurar el gráfico:

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

Este es el método del ejemplo de Desarrollador de Apple páginas que he modificado para asignar un soundfont a un determinado 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;
}

Entonces hice esto dos veces para obtener cada pista en 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);

Y por último:

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

Pero esto no asignar el soundfont para la samplerUnit2:

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

La asignación a samplerUnit funciona bien.Alguna idea de lo que me estoy perdiendo aquí?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top