Quiero programar un secuenciador de audio simple en el iphone, pero no puedo obtener un tiempo preciso. Los últimos días probé todas las técnicas de audio posibles en el iPhone, comenzando desde AudioServicesPlaySystemSound y AVAudioPlayer y OpenAL hasta AudioQueues.¿Cómo programar un secuenciador de audio preciso en tiempo real en el iPhone?
En mi último intento probé el motor de sonido CocosDenshion que usa openAL y permite cargar sonidos en múltiples búferes y luego reproducirlos cuando sea necesario. Aquí está el código básico:
init:
int channelGroups[1];
channelGroups[0] = 8;
soundEngine = [[CDSoundEngine alloc] init:channelGroups channelGroupTotal:1];
int i=0;
for(NSString *soundName in [NSArray arrayWithObjects:@"base1", @"snare1", @"hihat1", @"dit", @"snare", nil])
{
[soundEngine loadBuffer:i fileName:soundName fileType:@"wav"];
i++;
}
[NSTimer scheduledTimerWithTimeInterval:0.14 target:self selector:@selector(drumLoop:) userInfo:nil repeats:YES];
En la inicialización se crea el motor de sonido, cargue algunos sonidos a diferentes tampones y luego establecer el bucle secuenciador con NSTimer.
bucle de audio:
- (void)drumLoop:(NSTimer *)timer
{
for(int track=0; track<4; track++)
{
unsigned char note=pattern[track][step];
if(note)
[soundEngine playSound:note-1 channelGroupId:0 pitch:1.0f pan:.5 gain:1.0 loop:NO];
}
if(++step>=16)
step=0;
}
Eso es todo y funciona como debería, pero el tiempo es inestable e inestable. Tan pronto como sucede algo más (por ejemplo, dibujar en una vista) se desincroniza.
Según tengo entendido, el motor de sonido y openAL los búferes están cargados (en el código de inicio) y luego están listos para comenzar inmediatamente con alSourcePlay(source);
- ¿entonces el problema puede ser con NSTimer?
Ahora hay docenas de aplicaciones de secuenciador de sonido en la tienda de aplicaciones y tienen un horario preciso. Yo G. "idrum" tiene un ritmo estable perfecto incluso en 180 bpm cuando se hace zoom y dibujo. Entonces debe haber una solución.
¿Alguien tiene alguna idea?
¡Gracias por cualquier ayuda con anticipación!
Saludos,
Walchy
Gracias por su respuesta. Me llevó un paso más allá, pero desafortunadamente no al objetivo. Esto es lo que hice:
nextBeat=[[NSDate alloc] initWithTimeIntervalSinceNow:0.1];
[NSThread detachNewThreadSelector:@selector(drumLoop:) toTarget:self withObject:nil];
En la inicialización almaceno el tiempo para el siguiente latido y crear un nuevo hilo.
- (void)drumLoop:(id)info
{
[NSThread setThreadPriority:1.0];
while(1)
{
for(int track=0; track<4; track++)
{
unsigned char note=pattern[track][step];
if(note)
[soundEngine playSound:note-1 channelGroupId:0 pitch:1.0f pan:.5 gain:1.0 loop:NO];
}
if(++step>=16)
step=0;
NSDate *newNextBeat=[[NSDate alloc] initWithTimeInterval:0.1 sinceDate:nextBeat];
[nextBeat release];
nextBeat=newNextBeat;
[NSThread sleepUntilDate:nextBeat];
}
}
En el bucle de secuencia I establece la prioridad del hilo lo más alto posible y entra en un bucle infinito. Después de reproducir los sonidos, calculo el siguiente tiempo absoluto para el siguiente tiempo y envío el hilo a dormir hasta esta vez.
De nuevo, esto funciona y funciona de manera más estable que mis intentos sin NSThread, pero sigue siendo inestable si sucede algo más, especialmente cosas de GUI.
¿Hay alguna manera de obtener respuestas en tiempo real con NSThread en el iPhone?
Saludos,
Walchy
Creo @Walchy está fuera para el almuerzo ... Wonder cuales forma en que finalmente eligió hacerlo? –
Lamentablemente, no puedo publicar código de muestra, pero para la aplicación Reproducción en la tienda de aplicaciones, utilizamos una devolución de llamada para proporcionar los datos de audio que se leen de los archivos. Cada archivo tiene las mismas características de audio, por lo que para proporcionar un tiempo preciso, simplemente saltamos a ese punto de muestra en los datos del archivo de audio.Es súper preciso (descarga la aplicación y obtén el juego gratis del día). Podemos crear secciones de bucle y saltar a secciones en el archivo, todo mientras se reproducen más de 20 pistas a la vez (todavía no se ha alcanzado un límite de seguimiento). –