2011-07-07 9 views
8

He estado golpeando mi cabeza contra este problema toda la mañana.Reproducción de audio de un flujo continuo de datos (iOS)

Configuré una conexión a una fuente de datos que devuelve datos de audio (es un dispositivo de grabación, por lo que no hay una longitud establecida en los datos, los datos solo se transmiten). Me gusta si abre una transmisión a una radio)

y he logrado recibir todos los paquetes de datos en mi código. Ahora solo necesito jugarlo. Quiero reproducir los datos que están ingresando, por lo que no quiero hacer cola durante unos minutos ni nada, quiero usar los datos que estoy recibiendo en ese momento exacto y reproducirlos.

Ahora he estado buscando toda la mañana encontrando diferentes ejemplos, pero ninguno realmente fue presentado.

en la conexión

  • (void): (NSURLConnection ) Conexión didReceiveData: (NSData) de datos {
  • función

, el paquete "datos" es el paquete de audio. Intenté transmitirlo con AVPlayer, MFVideoPlayer, pero hasta ahora nada me ha funcionado. También probé mirando el Audiostreamer de mattgallagher, pero aún así no pude lograrlo.

¿Alguien aquí puede ayudar, tiene algunos (preferiblemente) ejemplos de trabajo?

Respuesta

2

Atención: la respuesta siguiente solo es válida si recibe datos PCM del servidor. Esto, por supuesto, nunca sucede. Es por eso que entre la reproducción del audio y la recepción de los datos necesita otro paso: la conversión de datos.

Dependiendo del formato, esto podría ser más o menos complicado, pero en general debería usar Audio Converter Services para este paso.

Debe usar -(void)connection:(NSURLConnection)connection didReceiveData:(NSData)data solo para llenar un búfer con los datos que provienen del servidor, jugarlo no debería tener nada que ver con este método.

Ahora, para reproducir los datos que 'almacenó' en la memoria utilizando el búfer, necesita usar unidades de audio y RemoteIO. Here is a good, comprehensive tutorial. Puede eliminar la parte "grabar" del tutorial ya que realmente no lo necesita.

Como se puede ver, que definen una devolución de llamada para la reproducción:

callbackStruct.inputProc = playbackCallback; 
callbackStruct.inputProcRefCon = self; 
status = AudioUnitSetProperty(audioUnit, 
           kAudioUnitProperty_SetRenderCallback, 
           kAudioUnitScope_Global, 
           kOutputBus, 
           &callbackStruct, 
           sizeof(callbackStruct)); 

y playbackCallback función tiene el siguiente aspecto:

static OSStatus playbackCallback(void *inRefCon, 
          AudioUnitRenderActionFlags *ioActionFlags, 
          const AudioTimeStamp *inTimeStamp, 
          UInt32 inBusNumber, 
          UInt32 inNumberFrames, 
          AudioBufferList *ioData) { 

    for (int i = 0 ; i < ioData->mNumberBuffers; i++){  
     AudioBuffer buffer = ioData->mBuffers[i]; 
     unsigned char *frameBuffer = buffer.mData; 
     for (int j = 0; j < inNumberFrames*2; j++){ 
      frameBuffer[j] = getNextPacket();//this here is a function you have to make to get the next chunk of bytes available in the stream buffer 
     } 
    } 

    return noErr; 
} 

Básicamente lo que hace es llenar el buffer ioData con el siguiente fragmento de bytes que deben reproducirse. Asegúrese de poner a cero (silenciar) el buffer ioData si no hay nuevos datos para reproducir (el reproductor se silencia si no hay suficientes datos en el buffer de transmisión).

Además, puede lograr lo mismo con OpenAL usando alSourceQueueBuffers y alSourceUnqueueBuffers para poner en cola buffers uno después del otro.

Eso es todo. ¡Feliz codificación!

+0

cab usted explica cómo hacer jugar ausio de venir bytes como bytes que vienen en la función de lectura nsinputstream – sajwan

+0

@valentin Radu estoy confundiendo para hacer buffer de audio de estoy obteniendo datos de este método y otra cosa sobre cómo llamar a esa llamada de reproducción ? gracias de antemano ser amable a servicial! –

Cuestiones relacionadas