/* * --- GSMP-COPYRIGHT-NOTE-BEGIN --- * * This copyright note is auto-generated by ./scripts/Create-CopyPatch. * Please add additional copyright information _after_ the line containing * the GSMP-COPYRIGHT-NOTE-END tag. Otherwise it might get removed by * the ./scripts/Create-CopyPatch script. Do not edit this copyright text! * * GSMP: pcm/include/template/ALSAConverter.tcc * General Sound Manipulation Program is Copyright (C) 2000 - 2004 * Valentin Ziegler and René Rebe * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2. A copy of the GNU General * Public License can be found in the file LICENSE. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANT- * ABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * Public License for more details. * * --- GSMP-COPYRIGHT-NOTE-END --- */ #ifndef LOWLEVEL__ALSACONVERTER_TMPL__ #error "This file is included by ALSAConverter.hh." #error "Include that file instead." #endif namespace GSMP { template void ALSAConverter::MixWrite (BasicStream* src, local_index start_index) { channel_index src_channels = src->Channels (); local_index write_size = src->UsedSize () - start_index; if (I::IsInterleaved) { // maybe we need to allocate a buffer if (write_size > allocated_samples) { if (buffer) { delete [] buffer; buffer = 0; } } if (!buffer) { buffer = new T [channels * write_size]; allocated_samples = write_size; } } else { // non-interleaved // maybe we need to allocate a buffer if (write_size > allocated_samples) { for (channel_index ch = 0; ch < channels; ++ch) { delete [] buffers [ch]; buffers [ch] = new T [channels * write_size]; } allocated_samples = write_size; } } // copy or interleave available data for (channel_index ch = 0; ch < channels; ++ch) { T* dst_ch_buffer; if (I::IsInterleaved) dst_ch_buffer= &(buffer [ch]); else dst_ch_buffer = buffers [ch]; // source channel for the card channel? if (ch < src_channels) { BasicStream::BufferType::pcm_type* src_ch_buffer = (*src)[ch]->data; src_ch_buffer += start_index; for (local_index i = 0; i < write_size; ++i) { *dst_ch_buffer = PcmConvert::Convert (*src_ch_buffer); ++ src_ch_buffer; if (I::IsInterleaved) dst_ch_buffer += channels; else ++ dst_ch_buffer; } } else // no source data - fill with zeros for missing channels { for (local_index i = 0; i < write_size; ++i) { *dst_ch_buffer = PcmTraits::Zero (); if (I::IsInterleaved) dst_ch_buffer += channels; else ++ dst_ch_buffer; } } } samples = write_size; }; template snd_pcm_sframes_t ALSAConverter::Write (ALSAPCM* pcm_card) { if (I::IsInterleaved) return pcm_card->WriteI ((void*)buffer, samples); else return pcm_card->WriteN ((void**)buffers, samples); }; template snd_pcm_sframes_t ALSAConverter::Read (ALSAPCM* pcm_card, local_index read_size) { if (I::IsInterleaved) { // maybe we need to allocate a buffer if (read_size > allocated_samples) { if (buffer) { delete [] buffer; buffer = 0; } } if (!buffer) { buffer = new T [ channels * read_size ]; allocated_samples = read_size; } } else { // non-interleaved // maybe we need to allocate a buffer if (read_size > allocated_samples) { for (channel_index ch = 0; ch < channels; ++ch) { delete [] buffers [ch]; buffers [ch] = new T [channels * read_size]; } allocated_samples = read_size; } } if (I::IsInterleaved) return pcm_card->ReadI ((void*)buffer, read_size); else return pcm_card->ReadN ((void**)buffers, read_size); } template void ALSAConverter::MixRead (BasicStream* dst, local_index read_size) { channel_index dst_channels = dst->Channels (); local_index start_index = dst->UsedSize (); // copy or interleave available data for (channel_index ch = 0; ch < dst_channels; ++ch) { BasicStream::BufferType::pcm_type* dst_ch_buffer = (*dst)[ch]->data; dst_ch_buffer += start_index; // dst channel for the card channel? if (ch < dst_channels) { T* src_ch_buffer; if (I::IsInterleaved) src_ch_buffer= &(buffer [ch]); else src_ch_buffer = buffers [ch]; for (local_index i = 0; i < read_size; ++i) { *dst_ch_buffer = PcmConvert::Convert (*src_ch_buffer); ++ dst_ch_buffer; if (I::IsInterleaved) src_ch_buffer += channels; else ++ src_ch_buffer; } } else // no data from card { *dst_ch_buffer = PcmTraits::Zero (); ++ dst_ch_buffer; } } } } // end namespace GSMP