libvorbis
-
Hi!
Ich möchte mit Libvorbis einen Audiostream zur Laufzeit encodiern bzw. decodieren. Das ganze ist für ein Voicechat gedacht. Momentan wird alles per PCM aufgenommen (44.1 kHz, Mono, 16 bit) und ich möchte um Traffic zu sparen den Vorbisfilter verwenden. Ich habe mir die Beispiele die bei libvorbis mitgeliefert werden angesehen, aber die behandeln nur das Umwandeln von .wav Dateien in .ogg Dateien. Wie also muss ich einen Stream umwandeln ohne unnötige Header etc. zu verwenden (um Traffic zu sparen)?
Wie kann man die Qualität der Umwandlung einstellen?
Gibt es irgendwelche Beispiele für das verwenden von Vorbis bei Audiostreaming?Hier noch der Thread der von waveInOpen aufgerufen wird:
DWORD WINAPI WaveInThread (void *Arg) { MSG Msg; int rv; rv = SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_TIME_CRITICAL); winexit_if(0 == rv, hWindow, "SetThreadPriority failed"); while (GetMessage (&Msg, NULL, 0, 0) == TRUE) { if (MM_WIM_DATA == Msg.message) { int rv = 0; WAVEHDR *Hdr = (WAVEHDR *) Msg.lParam; EnterCriticalSection(&remotefd_sem); if (remotefd != INVALID_SOCKET) { rv = sendto(remotefd, Hdr->lpData, sizeof(BufferIn[0]), 0, (struct sockaddr *) &remote, sizeof(remote)); if (rv < 0) { closesocket(remotefd); remotefd = INVALID_SOCKET; } } LeaveCriticalSection(&remotefd_sem); waveInAddBuffer(hWaveIn, Hdr, sizeof(*Hdr)); if (rv < 0) MessageBox(hWindow, "sendto failed", "WARNING", MB_OK); } } return 0; }
Danke für eure Hilfe!
-
Wenn du einen Voicechat schreiben willst, dann ist vorbis glaube ich nicht das richtige Encoding für dich, da die Kompression von vorbis ja recht langsam ist. Dient ja eher zum austauschen von Musik/Audio, die man einmal komprimiert hat.
Aber die Xiph-Leute haben für Voicesachen einen speziellen Codec entworfen: Speex.
-
Ok ich habe mir die speex lib heruntergeladen und gleich implementiert. Leider wird nur ein "knaksen" ausgegeben.
Sender des Streams:
//Encodieren: speex_bits_init(&bits); enc_state = speex_encoder_init(&speex_nb_mode); int quality = 10; speex_encoder_ctl(enc_state,SPEEX_SET_QUALITY,&quality); speex_bits_reset(&bits); speex_encode_int(enc_state,(spx_int16_t*)Hdr->lpData, &bits); save_length = speex_bits_write(&bits, buffer, BUFSIZE); speex_bits_destroy(&bits); speex_encoder_destroy(enc_state); //Adresse vorbereiten: addr.sin_family=AF_INET; addr.sin_port=htons(4567); rv = getAddrFromString("localhost",&addr); //Senden: sendto(audio_send_socket,buffer,save_length,0,(SOCKADDR*)&addr,sizeof(SOCKADDR_IN)); waveInAddBuffer(hWaveIn, Hdr, sizeof(*Hdr));
Empfänger des Streams:
rv = recvfrom(audio_socket,buffer,sizeof(buffer),0,(SOCKADDR*)&remoteAddr,&remoteAddrLen); if(rv==SOCKET_ERROR) {return 0;} for (i = 0; i < AUDIOBUFS; ++i) { if (0 == WaveHdrOut[i].dwUser) { //Decodiern: speex_bits_init(&bits); dec_state = speex_decoder_init(&speex_nb_mode); //speex_decoder_ctl(dec_state, SPEEX_SET_ENH, &enh); speex_bits_read_from(&bits, buffer, rv); speex_decode_int(dec_state, &bits, (short*)WaveHdrOut[i].lpData); speex_bits_destroy(&bits); speex_decoder_destroy(dec_state); //Audioausgabe: WaveHdrOut[i].dwUser = 1; // Buffer belegt markieren waveOutWrite(hWaveOut, WaveHdrOut + i, sizeof(WaveHdrOut[0])); break; } }
Was mache ich falsch?