2011-07-07 17 views
8

Przez cały ranek waliłem głową w ten problem.Odtwarzanie dźwięku z ciągłego strumienia danych (iOS)

Mam skonfigurowane połączenie ze źródłem danych, które zwraca dane audio (Jest to urządzenie nagrywające, więc nie ma ustawionej długości danych, dane po prostu są przesyłane strumieniowo, np. Jeśli chcesz otworzyć strumień do radia)

i udało mi się otrzymać wszystkie pakiety danych w moim kodzie. Teraz po prostu muszę to zagrać. Chcę odtwarzać nadchodzące dane, więc nie chcę czekać w kolejce przez kilka minut ani nic, chcę korzystać z danych, które otrzymuję w tym momencie i odtwarzać je.

Teraz przez cały ranek szukałem różnych przykładów, ale żadna z nich nie była tak naprawdę określona.

w (void) związku

  • (NSURLConnection ) połączenie didReceiveData (NSData) danych {

funkcja pakiet "dane" jest pakiet audio. Próbowałem przesyłać strumieniowo za pomocą AVPlayer, MFVideoPlayer, ale jak dotąd nic nie działało dla mnie. Próbował też spojrzeć na Audiostreamera firmy mattgallagher, ale wciąż nie był w stanie tego osiągnąć.

Ktoś tu może pomóc, ma niektóre (najlepiej) działające przykłady?

Odpowiedz

2

Ostrożnie: poniższa odpowiedź jest ważna tylko w przypadku otrzymania danych PCM z serwera. To się oczywiście nigdy nie zdarza. Dlatego między renderowaniem audio a odbiorem danych potrzebny jest kolejny krok: konwersja danych.

W zależności od formatu może to być mniej lub bardziej skomplikowane, ale generalnie powinieneś korzystać z Audio Converter Services w tym kroku.

Powinieneś używać tylko -(void)connection:(NSURLConnection)connection didReceiveData:(NSData)data, aby wypełnić bufor danymi pochodzącymi z serwera, więc odtwarzanie nie powinno mieć nic wspólnego z tą metodą.

Teraz, aby odtwarzać dane przechowywane w pamięci przy użyciu bufora, należy użyć urządzeń RemoteIO i audio. Here is a good, comprehensive tutorial. Możesz usunąć część "record" z samouczka, ponieważ tak naprawdę tego nie potrzebujesz.

Jak widać, określają one wywołania zwrotnego do odtwarzania:

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

i playbackCallback funkcja wygląda tak:

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

Zasadniczo co robi to, aby wypełnić bufor z ioData następny fragment bajtów, które muszą zostać odtworzone. Pamiętaj, aby wyzerować (wyciszyć) bufor ioData, jeśli nie ma nowych danych do odtworzenia (odtwarzacz jest wyciszany, jeśli w buforze strumienia nie ma wystarczającej ilości danych).

Co więcej, możesz osiągnąć to samo z OpenAL, używając alSourceQueueBuffers i alSourceUnqueueBuffers do kolejkowania buforów jeden po drugim.

To wszystko. Wesołego dorsza!

+0

kabina Wyjaśnij, jak odtwarzać ausio z nadchodzących bajtów jak bajty przychodzące w funkcji odczytu nsinputstream – sajwan

+0

@valentin Radu Jestem zagmatwany, aby bufor audio pochodził z tej metody, a jeszcze inną, jak zadzwonić, aby odtworzyć połączenie ? z góry dzięki uprzejmy i pomocny! –

Powiązane problemy