int	main(int argc, const char *argv[])
{
	int nins = 0;
	static const int MAX_INPUT_FILES = 32;
	const char *infiles[MAX_INPUT_FILES];
	const char *outfile = NULL;
	UInt32 layoutTag = 0;
#if TARGET_OS_WIN32
	InitializeQTML(0L);
#endif

	for (int i = 1; i < argc; ++i) {
		const char *arg = argv[i];
		if (arg[0] != '-') {
			if (nins >= MAX_INPUT_FILES) {
				fprintf(stderr, "too many input files\n\n");
				usage();
			}
			infiles[nins++] = arg;
		} else {
			arg += 1;
			if (arg[0] == 'o') {
				if (++i == argc) MissingArgument();
				outfile = argv[i];
			} else if (arg[0] == 'l' || !strcmp(arg, "-channellayout")) {
				if (++i == argc) MissingArgument();
				layoutTag = CAChannelLayouts::StringToConstant(argv[i]);
				if (layoutTag == CAChannelLayouts::kInvalidTag) {
					fprintf(stderr, "unknown channel layout tag: %s\n\n", argv[i]);
					usage();
				}
			} else {
				fprintf(stderr, "unknown argument: %s\n\n", arg - 1);
				usage();
			}
		}
	}
	
	if (nins < 2 || outfile == NULL)
		usage();
	
	try {
		if (layoutTag != 0) {
			CAAudioChannelLayout layout = CAAudioChannelLayout(layoutTag);
			Interleave(nins, infiles, outfile, &layout);
		} else
			Interleave(nins, infiles, outfile, NULL);
	}
	catch (CAXException &e) {
		char buf[256];
		fprintf(stderr, "Error: %s (%s)\n", e.mOperation, CAXException::FormatError(buf, e.mError));
		return 1;
	}
	catch (...) {
		fprintf(stderr, "An unknown error occurred\n");
		return 1;
	}
	return 0;
}
Beispiel #2
0
  void TurboCode::doEncode_term(const itpp::bvec &input, itpp::bvec *output) const
  {
    itpp::bvec parity1, tailbits1, tailParity1;
    rsc1_.GenParity(input, &parity1);
    rsc1_.Terminate(&tailbits1, &tailParity1);
    
    itpp::bvec interleaved = Interleave(input, interleaver_);
    itpp::bvec parity2, tailbits2, tailParity2;
    rsc2_.GenParity(interleaved, &parity2);
    rsc2_.Terminate(&tailbits2, &tailParity2);
    
    itpp::bvec t_output(3*interleaver_.size());
    for (int i = 0; i < interleaver_.size(); ++i){
      t_output[3*i] = input[i];
      t_output[3*i + 1] = parity1[i];
      t_output[3*i + 2] = parity2[i];
    } // for i

    itpp::bvec codeTail1(2*tailbits1.size());
    for (int i = 0; i < tailbits1.size(); ++i){
      codeTail1[2*i] = tailbits1[i];
      codeTail1[2*i + 1] = tailParity1[i];
    } // for i
    *output = itpp::concat(t_output, codeTail1);
    
    itpp::bvec codeTail2(2*tailbits2.size());
    for (int i = 0; i < tailbits2.size(); ++i){
      codeTail2[2*i] = tailbits2[i];
      codeTail2[2*i + 1] = tailParity2[i];
    } // for i
    *output = itpp::concat(*output, codeTail2);
  }
Beispiel #3
0
  void TurboCodeWithZP::Decoder_term(const itpp::cvec& in1,
                                     const itpp::cvec& in2,
                                     double n0, int iterations) const
  {
    // std::cout << "## zeroPadding_ = " << zeroPadding_.PadPositions() << std::endl;

    int memory = rsc1_.Constraint() - 1;
    static itpp::vec llrZeros(0);
    if (llrZeros.size() != memory){
      llrZeros.set_size(memory);
      llrZeros.zeros();
    } // if
    
    for (int ite = 0; ite < iterations; ++ite){
      itpp::vec llrToRsc1_mod = zeroPadding_.ModifyLLR(llrToRsc1_);
      
      itpp::vec llrFromRsc1;
      rsc1_.Decode(in1, llrToRsc1_mod, &llrFromRsc1, n0);
      
      itpp::vec llrFromRsc1_mod = zeroPadding_.ModifyLLR(llrFromRsc1);
            
      itpp::vec llrToRsc2 = Interleave(llrFromRsc1_mod.left(interleaver_.size()), interleaver_);
      llrToRsc2 = itpp::concat(llrToRsc2, llrZeros);

      itpp::vec llrFromRsc2;
      rsc2_.Decode(in2, llrToRsc2, &llrFromRsc2, n0);

      llrToRsc1_ = Deinterleave(llrFromRsc2.left(interleaver_.size()), interleaver_);
      llrToRsc1_ = itpp::concat(llrToRsc1_, llrZeros);
    } // for ite    
  }
Beispiel #4
0
  void TurboCode::Decoder_term(const itpp::cvec &in1,
                               const itpp::cvec &in2,
                               double n0, int iteration) const
  {
    int memory = rsc1_.Constraint() - 1;
    static itpp::vec llrZeros(0);
    if (llrZeros.size() != memory){
      llrZeros.set_size(memory);
      llrZeros.zeros();
    } // if

    for (int ite = 0; ite < iteration; ++ite){
      itpp::vec llrFromRsc1;
      rsc1_.Decode(in1, llrToRsc1_, &llrFromRsc1, n0);

      itpp::vec llrToRsc2 = Interleave(llrFromRsc1.left(interleaver_.size()), interleaver_);
      llrToRsc2 = itpp::concat(llrToRsc2, llrZeros);

      itpp::vec llrFromRsc2;
      rsc2_.Decode(in2, llrToRsc2, &llrFromRsc2, n0);

      llrToRsc1_ = Deinterleave(llrFromRsc2.left(interleaver_.size()), interleaver_);
      llrToRsc1_ = itpp::concat(llrToRsc1_, llrZeros);
    } // for ite

  }
Beispiel #5
0
  void TurboCode::SeparateReceivedSignal(const itpp::cvec &receivedSignal, itpp::cvec *in1, itpp::cvec *in2) const
  {
    int block = interleaver_.size();
    
    itpp::cvec r(block), parity1(block), parity2(block);

    for (int i = 0; i < block; ++i){
      r[i]       = receivedSignal[3*i];
      parity1[i] = receivedSignal[3*i + 1];
      parity2[i] = receivedSignal[3*i + 2];
    } // for i
    
    itpp::cvec interleaved_r = Interleave(r, interleaver_);
    
    in1->set_size(2*block);
    in2->set_size(2*block);
    for (int i = 0; i < block; ++i){
      (*in1)[2*i]     = r[i];
      (*in1)[2*i + 1] = parity1[i];

      (*in2)[2*i]     = interleaved_r[i];
      (*in2)[2*i + 1] = parity2[i];
    } // for i
    
  }
Beispiel #6
0
  void TurboCode::Decoder(const itpp::cvec &in1,
                          const itpp::cvec &in2, double n0, int iteration) const
  {
    for (int ite = 0; ite < iteration; ++ite){
      itpp::vec llrFromRsc1;
      rsc1_.Decode(in1, llrToRsc1_, &llrFromRsc1, n0);
      
      itpp::vec llrToRsc2 = Interleave(llrFromRsc1, interleaver_);

      itpp::vec llrFromRsc2;
      rsc2_.Decode(in2, llrToRsc2, &llrFromRsc2, n0);
      
      llrToRsc1_ = Deinterleave(llrFromRsc2, interleaver_);
    } // for ite
    
  }
Beispiel #7
0
  void TurboCode::doEncode(const itpp::bvec &input, itpp::bvec *output) const
  {
    itpp::bvec parity1 = rsc1_.GenParity(input);

    itpp::bvec interleaved = Interleave(input, interleaver_);

    itpp::bvec parity2 = rsc2_.GenParity(interleaved);

    output->set_size(3*input.size());
    for (int i = 0; i < input.size(); ++i){
      (*output)[3*i] = input[i];
      (*output)[3*i + 1] = parity1[i];
      (*output)[3*i + 2] = parity2[i];
    } // for i
    
  }
Beispiel #8
0
/*****************************************************************************
 * DecodePacket: decodes a Vorbis packet.
 *****************************************************************************/
static block_t *DecodePacket( decoder_t *p_dec, ogg_packet *p_oggpacket )
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    int           i_samples;

    INTERLEAVE_TYPE **pp_pcm;

    if( p_oggpacket->bytes &&
        vorbis_synthesis( &p_sys->vb, p_oggpacket ) == 0 )
        vorbis_synthesis_blockin( &p_sys->vd, &p_sys->vb );

    /* **pp_pcm is a multichannel float vector. In stereo, for
     * example, pp_pcm[0] is left, and pp_pcm[1] is right. i_samples is
     * the size of each channel. Convert the float values
     * (-1.<=range<=1.) to whatever PCM format and write it out */

    if( ( i_samples = vorbis_synthesis_pcmout( &p_sys->vd, &pp_pcm ) ) > 0 )
    {

        block_t *p_aout_buffer;

        if( decoder_UpdateAudioFormat( p_dec ) ) return NULL;
        p_aout_buffer =
            decoder_NewAudioBuffer( p_dec, i_samples );

        if( p_aout_buffer == NULL ) return NULL;

        /* Interleave the samples */
        Interleave( (INTERLEAVE_TYPE*)p_aout_buffer->p_buffer,
                    (const INTERLEAVE_TYPE**)pp_pcm, p_sys->vi.channels, i_samples,
                    p_sys->pi_chan_table);

        /* Tell libvorbis how many samples we actually consumed */
        vorbis_synthesis_read( &p_sys->vd, i_samples );

        /* Date management */
        p_aout_buffer->i_pts = date_Get( &p_sys->end_date );
        p_aout_buffer->i_length = date_Increment( &p_sys->end_date,
                                           i_samples ) - p_aout_buffer->i_pts;
        return p_aout_buffer;
    }
    else
    {
        return NULL;
    }
}
Beispiel #9
0
  /************************************************************************************
   * TurboCodeWithZP 
   * 
   * Implementation of Turbo Code with Zero Padding
   ************************************************************************************/
  void TurboCodeWithZP::Decoder(const itpp::cvec &in1,
                                const itpp::cvec &in2, double n0, int iterations) const
  {
    for (int ite = 0; ite < iterations; ++ite){
      itpp::vec llrToRsc1_mod = zeroPadding_.ModifyLLR(llrToRsc1_);
      
      itpp::vec llrFromRsc1;
      rsc1_.Decode(in1, llrToRsc1_mod, &llrFromRsc1, n0);

      itpp::vec llrFromRsc1_mod = zeroPadding_.ModifyLLR(llrFromRsc1);
      
      itpp::vec llrToRsc2 = Interleave(llrFromRsc1_mod.left(interleaver_.size()), interleaver_);

      itpp::vec llrFromRsc2;
      rsc2_.Decode(in2, llrToRsc2, &llrFromRsc2, n0);

      llrToRsc1_ = Deinterleave(llrFromRsc2.left(interleaver_.size()), interleaver_);
    } // for ite
    
  }
int main( int argc, char* argv[] )
{
/* ------------------ */
/* Parse command line */
/* ------------------ */

	gArgs.SetCmdLine( argc, argv );

/* ------------- */
/* Write new xml */
/* ------------- */

	Interleave();

/* ---- */
/* Done */
/* ---- */

	fprintf( flog, "\n" );
	fclose( flog );

	return 0;
}
Beispiel #11
0
void VertexUpdateCommand::copy()
{
    auto& buf = GetTemporaryBuffer();

    if (m_ctx_vb.data_ptr) {
        auto format = GuessVertexFormat(m_points, m_normals, m_colors, m_uvs, m_tangents);
        auto vertex_size = GetVertexSize(format);
        buf.resize(vertex_size * m_num_points);
        Interleave(buf.data(), format, m_num_points, m_points, m_normals, m_colors, m_uvs, m_tangents);
        memcpy(m_ctx_vb.data_ptr, buf.data(), buf.size());
    }

    if (m_ctx_ib.data_ptr && m_indices) {
        // Unity's mesh index is 16 bit
        // convert 32 bit indices -> 16 bit indices
        using index_t = uint16_t;
        buf.resize(sizeof(index_t) * m_num_indices);
        index_t *indices = (index_t*)buf.data();
        for (size_t i = 0; i < m_num_indices; ++i) {
            indices[i] = (index_t)m_indices[i];
        }
        memcpy(m_ctx_ib.data_ptr, buf.data(), buf.size());
    }
}
Beispiel #12
0
/*****************************************************************************
 * DoWork: decode an ATSC A/52 frame.
 *****************************************************************************/
static void DoWork( filter_t * p_filter,
                    aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
{
    filter_sys_t    *p_sys = p_filter->p_sys;
#ifdef LIBA52_FIXED
    sample_t        i_sample_level = (1 << 24);
#else
    sample_t        i_sample_level = 1;
#endif
    int             i_flags = p_sys->i_flags;
    int             i_bytes_per_block = 256 * p_sys->i_nb_channels
                      * sizeof(sample_t);
    int             i;

    /* Do the actual decoding now. */
    a52_frame( p_sys->p_liba52, p_in_buf->p_buffer,
               &i_flags, &i_sample_level, 0 );

    if ( (i_flags & A52_CHANNEL_MASK) != (p_sys->i_flags & A52_CHANNEL_MASK)
          && !p_sys->b_dontwarn )
    {
        msg_Warn( p_filter,
                  "liba52 couldn't do the requested downmix 0x%x->0x%x",
                  p_sys->i_flags  & A52_CHANNEL_MASK,
                  i_flags & A52_CHANNEL_MASK );

        p_sys->b_dontwarn = 1;
    }

    if( !p_sys->b_dynrng )
    {
        a52_dynrng( p_sys->p_liba52, NULL, NULL );
    }

    for ( i = 0; i < 6; i++ )
    {
        sample_t * p_samples;

        if( a52_block( p_sys->p_liba52 ) )
        {
            msg_Warn( p_filter, "a52_block failed for block %d", i );
        }

        p_samples = a52_samples( p_sys->p_liba52 );

        if ( ((p_sys->i_flags & A52_CHANNEL_MASK) == A52_CHANNEL1
               || (p_sys->i_flags & A52_CHANNEL_MASK) == A52_CHANNEL2
               || (p_sys->i_flags & A52_CHANNEL_MASK) == A52_MONO)
              && (p_filter->fmt_out.audio.i_physical_channels
                   & (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT)) )
        {
            Duplicate( (sample_t *)(p_out_buf->p_buffer + i * i_bytes_per_block),
                       p_samples );
        }
        else if ( p_filter->fmt_out.audio.i_original_channels
                    & AOUT_CHAN_REVERSESTEREO )
        {
            Exchange( (sample_t *)(p_out_buf->p_buffer + i * i_bytes_per_block),
                      p_samples );
        }
        else
        {
            /* Interleave the *$£%ù samples. */
            Interleave( (sample_t *)(p_out_buf->p_buffer + i * i_bytes_per_block),
                        p_samples, p_sys->i_nb_channels, p_sys->pi_chan_table);
        }
    }

    p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
    p_out_buf->i_buffer = i_bytes_per_block * 6;
}
Beispiel #13
0
/*****************************************************************************
 * DoWork: decode a DTS frame.
 *****************************************************************************/
static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter,
                    aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
{
    filter_sys_t    *p_sys = (filter_sys_t *)p_filter->p_sys;
    sample_t        i_sample_level = 1;
    int             i_flags = p_sys->i_flags;
    int             i_bytes_per_block = 256 * p_sys->i_nb_channels
                      * sizeof(float);
    int             i;

    /*
     * Do the actual decoding now.
     */

    /* Needs to be called so the decoder knows which type of bitstream it is
     * dealing with. */
    int i_sample_rate, i_bit_rate, i_frame_length;
    if( !dts_syncinfo( p_sys->p_libdts, p_in_buf->p_buffer, &i_flags,
                       &i_sample_rate, &i_bit_rate, &i_frame_length ) )
    {
        msg_Warn( p_filter, "libdts couldn't sync on frame" );
        p_out_buf->i_nb_samples = p_out_buf->i_nb_bytes = 0;
        return;
    }

    i_flags = p_sys->i_flags;
    dts_frame( p_sys->p_libdts, p_in_buf->p_buffer,
               &i_flags, &i_sample_level, 0 );

    if ( (i_flags & DTS_CHANNEL_MASK) != (p_sys->i_flags & DTS_CHANNEL_MASK)
          && !p_sys->b_dontwarn )
    {
        msg_Warn( p_filter,
                  "libdts couldn't do the requested downmix 0x%x->0x%x",
                  p_sys->i_flags  & DTS_CHANNEL_MASK,
                  i_flags & DTS_CHANNEL_MASK );

        p_sys->b_dontwarn = 1;
    }

    if( 0)//!p_sys->b_dynrng )
    {
        dts_dynrng( p_sys->p_libdts, NULL, NULL );
    }

    for ( i = 0; i < dts_blocks_num(p_sys->p_libdts); i++ )
    {
        sample_t * p_samples;

        if( dts_block( p_sys->p_libdts ) )
        {
            msg_Warn( p_filter, "dts_block failed for block %d", i );
            break;
        }

        p_samples = dts_samples( p_sys->p_libdts );

        if ( (p_sys->i_flags & DTS_CHANNEL_MASK) == DTS_MONO
              && (p_filter->output.i_physical_channels 
                   & (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT)) )
        {
            Duplicate( (float *)(p_out_buf->p_buffer + i * i_bytes_per_block),
                       p_samples );
        }
        else if ( p_filter->output.i_original_channels
                    & AOUT_CHAN_REVERSESTEREO )
        {
            Exchange( (float *)(p_out_buf->p_buffer + i * i_bytes_per_block),
                      p_samples );
        }
        else
        {
            /* Interleave the *$£%ù samples. */
            Interleave( (float *)(p_out_buf->p_buffer + i * i_bytes_per_block),
                        p_samples, p_sys->i_nb_channels, p_sys->pi_chan_table);
        }
    }

    p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
    p_out_buf->i_nb_bytes = i_bytes_per_block * i;
}
Beispiel #14
0
  void Decompress(const FasTC::DecompressionJob &dcj,
                  const EWrapMode wrapMode,
                  bool bDebugImages) {
    const bool bTwoBitMode = dcj.Format() == FasTC::eCompressionFormat_PVRTC2;
    const uint32 w = dcj.Width();
    const uint32 h = dcj.Height();

    assert(w > 0);
    assert(h > 0);
    assert(bTwoBitMode || w % 4 == 0);
    assert(!bTwoBitMode || w % 8 == 0);
    assert(h % 4 == 0);

    // First, extract all of the block information...
    std::vector<Block> blocks;

    const uint32 blocksW = bTwoBitMode? (w / 8) : (w / 4);
    const uint32 blocksH = h / 4;
    blocks.reserve(blocksW * blocksH);

    for(uint32 j = 0; j < blocksH; j++) {
      for(uint32 i = 0; i < blocksW; i++) {

        // The blocks are initially arranged in morton order. Let's
        // linearize them...
        uint32 idx = Interleave(j, i);

        uint32 offset = idx * kBlockSize;
        blocks.push_back( Block(dcj.InBuf() + offset) );
      }
    }

    assert(blocks.size() > 0);

    // Extract the endpoints into A and B images
    Image imgA(blocksW, blocksH);
    Image imgB(blocksW, blocksH);

    for(uint32 j = 0; j < blocksH; j++) {
      for(uint32 i = 0; i < blocksW; i++) {

        uint32 idx = j * blocksW + i;
        assert(idx < static_cast<uint32>(blocks.size()));

        Block &b = blocks[idx];
        imgA(i, j) = b.GetColorA();
        imgB(i, j) = b.GetColorB();
      }
    }

    // Change the pixel mode so that all of the pixels are at the same
    // bit depth.
    const uint8 scaleDepths[4] = { 4, 5, 5, 5 };
    imgA.ChangeBitDepth(scaleDepths);
    if(bDebugImages)
      imgA.DebugOutput("UnscaledImgA");
    imgB.ChangeBitDepth(scaleDepths);
    if(bDebugImages)
      imgB.DebugOutput("UnscaledImgB");

    // Go through and change the alpha value of any pixel that came from
    // a transparent block. For some reason, alpha is not treated the same
    // as the other channels (to minimize hardware costs?) and the channels
    // do not their MSBs replicated.
    for(uint32 j = 0; j < blocksH; j++) {
      for(uint32 i = 0; i < blocksW; i++) {
        const uint32 blockIdx = j * blocksW + i;
        Block &b = blocks[blockIdx];

        uint8 bitDepths[4];
        b.GetColorA().GetBitDepth(bitDepths);
        if(bitDepths[0] > 0) {
          Pixel &p = imgA(i, j);
          p.A() = p.A() & 0xFE;
        }

        b.GetColorB().GetBitDepth(bitDepths);
        if(bitDepths[0] > 0) {
          Pixel &p = imgB(i, j);
          p.A() = p.A() & 0xFE;
        }
      }
    }

    // Bilinearly upscale the images.
    if(bTwoBitMode) {
      imgA.BilinearUpscale(3, 2, wrapMode);
      imgB.BilinearUpscale(3, 2, wrapMode);
    } else {
      imgA.BilinearUpscale(2, 2, wrapMode);
      imgB.BilinearUpscale(2, 2, wrapMode);
    }

    if(bDebugImages) {
      imgA.DebugOutput("RawScaledImgA");
      imgB.DebugOutput("RawScaledImgB");
    }

    // Change the bitdepth to full resolution
    imgA.ExpandTo8888();
    imgB.ExpandTo8888();

    if(bDebugImages) {
      imgA.DebugOutput("ScaledImgA");
      imgB.DebugOutput("ScaledImgB");
    }

    if(bTwoBitMode) {
      Decompress2BPP(imgA, imgB, blocks, dcj.OutBuf(), bDebugImages);
    } else {
      Decompress4BPP(imgA, imgB, blocks, dcj.OutBuf(), bDebugImages);
    }
  }
Beispiel #15
0
Datei: dca.c Projekt: etix/vlc
static int Decode( decoder_t *p_dec, block_t *p_in_buf )
{
    decoder_sys_t  *p_sys = p_dec->p_sys;

    if (p_in_buf == NULL) /* No Drain */
        return VLCDEC_SUCCESS;

    sample_t i_sample_level = 1;
    int  i_flags = p_sys->i_flags;
    size_t i_bytes_per_block = 256 * p_sys->i_nb_channels * sizeof(float);

    block_t *p_out_buf = block_Alloc( 6 * i_bytes_per_block );
    if( unlikely(p_out_buf == NULL) )
        goto out;

    /*
     * Do the actual decoding now.
     */

    /* Needs to be called so the decoder knows which type of bitstream it is
     * dealing with. */
    int i_sample_rate, i_bit_rate, i_frame_length;
    if( !dca_syncinfo( p_sys->p_libdca, p_in_buf->p_buffer, &i_flags,
                       &i_sample_rate, &i_bit_rate, &i_frame_length ) )
    {
        msg_Warn( p_dec, "libdca couldn't sync on frame" );
        p_out_buf->i_nb_samples = p_out_buf->i_buffer = 0;
        goto out;
    }

    i_flags = p_sys->i_flags;
    dca_frame( p_sys->p_libdca, p_in_buf->p_buffer,
               &i_flags, &i_sample_level, 0 );

    if ( (i_flags & DCA_CHANNEL_MASK) != (p_sys->i_flags & DCA_CHANNEL_MASK)
          && !p_sys->b_dontwarn )
    {
        msg_Warn( p_dec,
                  "libdca couldn't do the requested downmix 0x%x->0x%x",
                  p_sys->i_flags  & DCA_CHANNEL_MASK,
                  i_flags & DCA_CHANNEL_MASK );

        p_sys->b_dontwarn = 1;
    }

    if( 0)//!p_sys->b_dynrng )
    {
        dca_dynrng( p_sys->p_libdca, NULL, NULL );
    }

    for( int i = 0; i < dca_blocks_num(p_sys->p_libdca); i++ )
    {
        sample_t * p_samples;

        if( dca_block( p_sys->p_libdca ) )
        {
            msg_Warn( p_dec, "dca_block failed for block %d", i );
            break;
        }

        p_samples = dca_samples( p_sys->p_libdca );

        if ( (p_sys->i_flags & DCA_CHANNEL_MASK) == DCA_MONO
              && (p_dec->fmt_out.audio.i_physical_channels
                   & (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT)) )
        {
            Duplicate( (float *)(p_out_buf->p_buffer + i * i_bytes_per_block),
                       p_samples );
        }
        else if ( p_dec->fmt_out.audio.i_original_channels
                    & AOUT_CHAN_REVERSESTEREO )
        {
            Exchange( (float *)(p_out_buf->p_buffer + i * i_bytes_per_block),
                      p_samples );
        }
        else
        {
            /* Interleave the *$£%ù samples. */
            Interleave( (float *)(p_out_buf->p_buffer + i * i_bytes_per_block),
                        p_samples, p_sys->i_nb_channels, p_sys->pi_chan_table);
        }
    }

    p_out_buf->i_nb_samples = dca_blocks_num(p_sys->p_libdca) * 256;
    p_out_buf->i_buffer = p_in_buf->i_nb_samples * sizeof(float) * p_sys->i_nb_channels;
    p_out_buf->i_dts = p_in_buf->i_dts;
    p_out_buf->i_pts = p_in_buf->i_pts;
    p_out_buf->i_length = p_in_buf->i_length;
out:
    if (p_out_buf != NULL)
        decoder_QueueAudio(p_dec, p_out_buf);
    block_Release( p_in_buf );
    return VLCDEC_SUCCESS;
}