mirror of
https://github.com/badaix/snapcast.git
synced 2025-05-25 06:56:15 +02:00
decoder gets sample format from header
This commit is contained in:
parent
1d1ef239b2
commit
eed7f287fb
10 changed files with 216 additions and 114 deletions
|
@ -16,12 +16,15 @@
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#include "oggDecoder.h"
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
#include <cmath>
|
||||
#include <vorbis/vorbisenc.h>
|
||||
|
||||
#include "oggDecoder.h"
|
||||
#include "common/snapException.h"
|
||||
#include "common/log.h"
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
@ -54,24 +57,24 @@ bool OggDecoder::decode(msg::PcmChunk* chunk)
|
|||
stream initial header) We need the first page to get the stream
|
||||
serialno. */
|
||||
bytes = chunk->payloadSize;
|
||||
buffer=ogg_sync_buffer(&oy, bytes);
|
||||
buffer = ogg_sync_buffer(&oy, bytes);
|
||||
memcpy(buffer, chunk->payload, bytes);
|
||||
ogg_sync_wrote(&oy,bytes);
|
||||
|
||||
|
||||
chunk->payloadSize = 0;
|
||||
convsize=4096;//bytes/vi.channels;
|
||||
convsize = 4096;//bytes/vi.channels;
|
||||
/* The rest is just a straight decode loop until end of stream */
|
||||
// while(!eos){
|
||||
while(true)
|
||||
{
|
||||
int result=ogg_sync_pageout(&oy,&og);
|
||||
if (result==0)
|
||||
int result = ogg_sync_pageout(&oy, &og);
|
||||
if (result == 0)
|
||||
break; /* need more data */
|
||||
if(result<0)
|
||||
if(result < 0)
|
||||
{
|
||||
/* missing or corrupt data at this page position */
|
||||
fprintf(stderr,"Corrupt or missing data in bitstream; continuing...\n");
|
||||
logE << "Corrupt or missing data in bitstream; continuing...\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -79,19 +82,19 @@ bool OggDecoder::decode(msg::PcmChunk* chunk)
|
|||
this point */
|
||||
while(1)
|
||||
{
|
||||
result=ogg_stream_packetout(&os,&op);
|
||||
result = ogg_stream_packetout(&os, &op);
|
||||
|
||||
if(result==0)
|
||||
if (result == 0)
|
||||
break; /* need more data */
|
||||
if(result<0)
|
||||
if (result < 0)
|
||||
continue; /* missing or corrupt data at this page position */
|
||||
/* no reason to complain; already complained above */
|
||||
/* we have a packet. Decode it */
|
||||
float **pcm;
|
||||
int samples;
|
||||
|
||||
if(vorbis_synthesis(&vb,&op)==0) /* test for success! */
|
||||
vorbis_synthesis_blockin(&vd,&vb);
|
||||
if (vorbis_synthesis(&vb,&op) == 0) /* test for success! */
|
||||
vorbis_synthesis_blockin(&vd, &vb);
|
||||
/*
|
||||
|
||||
**pcm is a multichannel float vector. In stereo, for
|
||||
|
@ -99,17 +102,17 @@ bool OggDecoder::decode(msg::PcmChunk* chunk)
|
|||
the size of each channel. Convert the float values
|
||||
(-1.<=range<=1.) to whatever PCM format and write it out */
|
||||
|
||||
while((samples=vorbis_synthesis_pcmout(&vd,&pcm))>0)
|
||||
while ((samples = vorbis_synthesis_pcmout(&vd, &pcm)) > 0)
|
||||
{
|
||||
int bout=(samples<convsize?samples:convsize);
|
||||
int bout = (samples<convsize?samples:convsize);
|
||||
//cout << "samples: " << samples << ", convsize: " << convsize << "\n";
|
||||
/* convert floats to 16 bit signed ints (host order) and
|
||||
interleave */
|
||||
for(int i=0; i<vi.channels; i++)
|
||||
{
|
||||
ogg_int16_t *ptr=convbuffer+i;
|
||||
float *mono=pcm[i];
|
||||
for(int j=0; j<bout; j++)
|
||||
float *mono=pcm[i];
|
||||
for (int j=0; j<bout; j++)
|
||||
{
|
||||
int val=floor(mono[j]*32767.f+.5f);
|
||||
/* might as well guard against clipping */
|
||||
|
@ -140,73 +143,56 @@ bool OggDecoder::decode(msg::PcmChunk* chunk)
|
|||
}
|
||||
|
||||
|
||||
bool OggDecoder::setHeader(msg::Header* chunk)
|
||||
msg::SampleFormat OggDecoder::setHeader(msg::Header* chunk)
|
||||
{
|
||||
bytes = chunk->payloadSize;
|
||||
buffer=ogg_sync_buffer(&oy, bytes);
|
||||
memcpy(buffer, chunk->payload, bytes);
|
||||
ogg_sync_wrote(&oy,bytes);
|
||||
ogg_sync_wrote(&oy, bytes);
|
||||
|
||||
if(ogg_sync_pageout(&oy,&og)!=1)
|
||||
{
|
||||
fprintf(stderr,"Input does not appear to be an Ogg bitstream.\n");
|
||||
return false;
|
||||
}
|
||||
if (ogg_sync_pageout(&oy, &og) != 1)
|
||||
throw SnapException("Input does not appear to be an Ogg bitstream");
|
||||
|
||||
ogg_stream_init(&os,ogg_page_serialno(&og));
|
||||
|
||||
vorbis_info_init(&vi);
|
||||
vorbis_comment_init(&vc);
|
||||
if(ogg_stream_pagein(&os,&og)<0)
|
||||
{
|
||||
fprintf(stderr,"Error reading first page of Ogg bitstream data.\n");
|
||||
return false;
|
||||
}
|
||||
if (ogg_stream_pagein(&os, &og) < 0)
|
||||
throw SnapException("Error reading first page of Ogg bitstream data");
|
||||
|
||||
if(ogg_stream_packetout(&os,&op)!=1)
|
||||
{
|
||||
fprintf(stderr,"Error reading initial header packet.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(vorbis_synthesis_headerin(&vi,&vc,&op)<0)
|
||||
{
|
||||
fprintf(stderr,"This Ogg bitstream does not contain Vorbis audio data.\n");
|
||||
return false;
|
||||
}
|
||||
if (ogg_stream_packetout(&os, &op) != 1)
|
||||
throw SnapException("Error reading initial header packet");
|
||||
|
||||
if (vorbis_synthesis_headerin(&vi, &vc, &op) < 0)
|
||||
throw SnapException("This Ogg bitstream does not contain Vorbis audio data");
|
||||
|
||||
int i(0);
|
||||
while(i<2)
|
||||
while (i < 2)
|
||||
{
|
||||
while(i<2)
|
||||
while (i < 2)
|
||||
{
|
||||
int result=ogg_sync_pageout(&oy,&og);
|
||||
if(result==0)
|
||||
int result=ogg_sync_pageout(&oy, &og);
|
||||
if (result == 0)
|
||||
break; /* Need more data */
|
||||
/* Don't complain about missing or corrupt data yet. We'll
|
||||
catch it at the packet output phase */
|
||||
if(result==1)
|
||||
if (result == 1)
|
||||
{
|
||||
ogg_stream_pagein(&os,&og); /* we can ignore any errors here as they'll also become apparent at packetout */
|
||||
while(i<2)
|
||||
ogg_stream_pagein(&os, &og); /* we can ignore any errors here as they'll also become apparent at packetout */
|
||||
while (i < 2)
|
||||
{
|
||||
result=ogg_stream_packetout(&os,&op);
|
||||
if(result==0)
|
||||
result=ogg_stream_packetout(&os, &op);
|
||||
if (result == 0)
|
||||
break;
|
||||
if(result<0)
|
||||
{
|
||||
/* Uh oh; data at some point was corrupted or missing!
|
||||
We can't tolerate that in a header. Die. */
|
||||
fprintf(stderr,"Corrupt secondary header. Exiting.\n");
|
||||
return false;
|
||||
}
|
||||
result=vorbis_synthesis_headerin(&vi,&vc,&op);
|
||||
if(result<0)
|
||||
{
|
||||
fprintf(stderr,"Corrupt secondary header. Exiting.\n");
|
||||
return false;
|
||||
}
|
||||
/// Uh oh; data at some point was corrupted or missing!
|
||||
/// We can't tolerate that in a header. Die. */
|
||||
if (result < 0)
|
||||
throw SnapException("Corrupt secondary header. Exiting.");
|
||||
|
||||
result=vorbis_synthesis_headerin(&vi, &vc, &op);
|
||||
if (result < 0)
|
||||
throw SnapException("Corrupt secondary header. Exiting.");
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
@ -220,18 +206,19 @@ bool OggDecoder::setHeader(msg::Header* chunk)
|
|||
fprintf(stderr,"%s\n",*ptr);
|
||||
++ptr;
|
||||
}
|
||||
fprintf(stderr,"\nBitstream is %d channel, %ldHz\n",vi.channels,vi.rate);
|
||||
fprintf(stderr,"Encoded by: %s\n\n",vc.vendor);
|
||||
|
||||
/* OK, got and parsed all three headers. Initialize the Vorbis
|
||||
packet->PCM decoder. */
|
||||
if(vorbis_synthesis_init(&vd,&vi)==0) /* central decode state */
|
||||
vorbis_block_init(&vd,&vb); /* local state for most of the decode
|
||||
so multiple block decodes can
|
||||
proceed in parallel. We could init
|
||||
multiple vorbis_block structures
|
||||
for vd here */
|
||||
return false;
|
||||
logE << "Encoded by: " << vc.vendor << "\n";
|
||||
|
||||
/// OK, got and parsed all three headers. Initialize the Vorbis packet->PCM decoder.
|
||||
if (vorbis_synthesis_init(&vd, &vi) == 0)
|
||||
vorbis_block_init(&vd, &vb);
|
||||
/// central decode state
|
||||
/// local state for most of the decode so multiple block decodes can proceed
|
||||
/// in parallel. We could init multiple vorbis_block structures for vd here
|
||||
|
||||
|
||||
msg::SampleFormat sampleFormat(vi.rate, 16, vi.channels);
|
||||
return sampleFormat;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue