sintonia/library/ecasound-2.7.2/libecasound/eca-audio-format.cpp

332 lines
7.9 KiB
C++

// ------------------------------------------------------------------------
// eca-audio-format.cpp: Class for representing audio format parameters
// Copyright (C) 1999-2002,2004 Kai Vehmanen
//
// Attributes:
// eca-style-version: 2
//
// 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; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// ------------------------------------------------------------------------
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <kvutils/kvu_dbc.h>
#include <kvutils/kvu_numtostr.h>
#include "eca-audio-format.h"
#include "eca-error.h"
ECA_AUDIO_FORMAT::ECA_AUDIO_FORMAT(int channels,
long int srate,
ECA_AUDIO_FORMAT::Sample_format format,
bool ileaved)
{
set_channels(channels);
set_samples_per_second(srate);
set_sample_format(format);
toggle_interleaved_channels(ileaved);
}
ECA_AUDIO_FORMAT::ECA_AUDIO_FORMAT(void)
{
set_channels(0);
set_samples_per_second(-1);
set_sample_format(sfmt_none);
toggle_interleaved_channels(true);
}
ECA_AUDIO_FORMAT::~ECA_AUDIO_FORMAT(void)
{
}
ECA_AUDIO_FORMAT ECA_AUDIO_FORMAT::audio_format(void) const
{
return ECA_AUDIO_FORMAT(channels(),
samples_per_second(),
sample_format(),
interleaved_channels());
}
ECA_AUDIO_FORMAT::Sample_format ECA_AUDIO_FORMAT::sample_format(void) const
{
Sample_format format (sfmt_none);
try {
format = string_to_sample_format(format_string());
}
catch(...) {}
return format;
}
/**
* Sets audio format to that of 'f'.
*/
void ECA_AUDIO_FORMAT::set_audio_format(const ECA_AUDIO_FORMAT& f)
{
set_channels(f.channels());
set_sample_format(f.sample_format());
set_samples_per_second(f.samples_per_second());
toggle_interleaved_channels(f.interleaved_channels());
}
void ECA_AUDIO_FORMAT::set_sample_format(ECA_AUDIO_FORMAT::Sample_format sfmt) throw(ECA_ERROR&)
{
switch(sfmt)
{
case sfmt_none:
sc_rep = sc_unsigned;
update_sample_endianess(se_native);
align_rep = 0;
break;
case sfmt_u8:
sc_rep = sc_unsigned;
update_sample_endianess(se_native);
align_rep = 1;
break;
case sfmt_s8:
sc_rep = sc_signed;
update_sample_endianess(se_native);
align_rep = 1;
break;
case sfmt_s16:
sc_rep = sc_signed;
update_sample_endianess(se_native);
align_rep = 2;
break;
case sfmt_s16_le:
sc_rep = sc_signed;
update_sample_endianess(se_little);
align_rep = 2;
break;
case sfmt_s16_be:
sc_rep = sc_signed;
update_sample_endianess(se_big);
align_rep = 2;
break;
case sfmt_s24:
sc_rep = sc_signed;
update_sample_endianess(se_native);
align_rep = 3;
break;
case sfmt_s24_le:
sc_rep = sc_signed;
update_sample_endianess(se_little);
align_rep = 3;
break;
case sfmt_s24_be:
sc_rep = sc_signed;
update_sample_endianess(se_big);
align_rep = 3;
break;
case sfmt_s32:
sc_rep = sc_signed;
update_sample_endianess(se_native);
align_rep = 4;
break;
case sfmt_s32_le:
sc_rep = sc_signed;
update_sample_endianess(se_little);
align_rep = 4;
break;
case sfmt_f32:
sc_rep = sc_float;
update_sample_endianess(se_native);
align_rep = 4;
break;
case sfmt_s32_be:
sc_rep = sc_signed;
update_sample_endianess(se_big);
align_rep = 4;
break;
case sfmt_f32_le:
sc_rep = sc_float;
update_sample_endianess(se_little);
align_rep = 4;
break;
case sfmt_f32_be:
sc_rep = sc_float;
update_sample_endianess(se_big);
align_rep = 4;
break;
case sfmt_f64:
sc_rep = sc_float;
update_sample_endianess(se_native);
align_rep = 8;
break;
case sfmt_f64_le:
sc_rep = sc_float;
update_sample_endianess(se_little);
align_rep = 8;
break;
case sfmt_f64_be:
sc_rep = sc_float;
update_sample_endianess(se_big);
align_rep = 8;
break;
default: { throw(ECA_ERROR("ECA_AUDIO_FORMAT","Audio format not supported!")); }
}
DBC_ENSURE(se_rep == se_big || se_rep == se_little);
}
int ECA_AUDIO_FORMAT::bits(void) const
{
return align_rep * 8;
}
void ECA_AUDIO_FORMAT::set_channels(int v)
{
channels_rep = v;
}
void ECA_AUDIO_FORMAT::toggle_interleaved_channels(bool v)
{
ileaved_rep = v;
}
ECA_AUDIO_FORMAT::Sample_format ECA_AUDIO_FORMAT::string_to_sample_format(const std::string& str) const throw(ECA_ERROR&)
{
Sample_format sfmt = sfmt_none;
if (str == "u8") sfmt = sfmt_u8;
else if (str == "s16") sfmt = sfmt_s16;
else if (str == "s16_le") sfmt = sfmt_s16_le;
else if (str == "s16_be") sfmt = sfmt_s16_be;
else if (str == "s24") sfmt = sfmt_s24;
else if (str == "s24_le") sfmt = sfmt_s24_le;
else if (str == "s24_be") sfmt = sfmt_s24_be;
else if (str == "s32") sfmt = sfmt_s32;
else if (str == "s32_le") sfmt = sfmt_s32_le;
else if (str == "s32_be") sfmt = sfmt_s32_be;
else if (str == "f32") sfmt = sfmt_f32;
else if (str == "f32_le") sfmt = sfmt_f32_le;
else if (str == "f32_be") sfmt = sfmt_f32_be;
else if (str == "f64") sfmt = sfmt_f64;
else if (str == "f64_le") sfmt = sfmt_f64_le;
else if (str == "f64_be") sfmt = sfmt_f64_be;
else if (str == "8") sfmt = sfmt_u8;
else if (str == "16") sfmt = sfmt_s16;
else if (str == "24") sfmt = sfmt_s24;
else if (str == "32") sfmt = sfmt_s32;
else {
if (str != "none")
throw(ECA_ERROR("ECA_AUDIO_FORMAT", "Unknown sample format \""
+ str + "\"."));
}
return sfmt;
}
void ECA_AUDIO_FORMAT::set_sample_format_string(const std::string& f_str) throw(ECA_ERROR&)
{
/* note, may raise an exception */
set_sample_format(string_to_sample_format(f_str));
}
/**
* Internal helper function that sets sample endianess
* and if needed, expands native to either little or big
* byteorder.
*
* @see set_sample_endianess
*/
void ECA_AUDIO_FORMAT::update_sample_endianess(ECA_AUDIO_FORMAT::Sample_endianess v)
{
if (v == se_native) {
#ifdef WORDS_BIGENDIAN
se_rep = se_big;
#else
se_rep = se_little;
#endif
}
else {
se_rep = v;
}
}
void ECA_AUDIO_FORMAT::set_sample_endianess(ECA_AUDIO_FORMAT::Sample_endianess v)
{
update_sample_endianess(v);
/* make sure classes that reimplement set_sample_format
* see the change in sample endianess */
set_sample_format_string(format_string());
DBC_ENSURE(se_rep == se_big || se_rep == se_little);
}
void ECA_AUDIO_FORMAT::set_sample_coding(ECA_AUDIO_FORMAT::Sample_coding v)
{
sc_rep = v;
/* make sure classes that reimplement set_sample_format
* see the change in sample coding */
set_sample_format_string(format_string());
}
string ECA_AUDIO_FORMAT::format_string(void) const
{
std::string format;
if (align_rep > 0) {
/* coding */
switch(sc_rep)
{
case sc_unsigned: format += "u"; break;
case sc_signed: format += "s"; break;
case sc_float: format += "f"; break;
}
/* bits */
format += kvu_numtostr(bits());
DBC_CHECK(se_rep == se_big || se_rep == se_little);
/* endianess */
if (align_rep > 1) {
if (se_rep == se_little) {
format += "_le";
}
else {
format += "_be";
}
}
}
else {
/* align_rep == 0 -> sfmt is yet unspecified */
format = "none";
}
return format;
}