You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
271 lines
9.2 KiB
271 lines
9.2 KiB
15 years ago
|
/***************************************************************************
|
||
|
soundformat.cpp - description
|
||
|
-------------------
|
||
|
begin : Sun Aug 1 2004
|
||
|
copyright : (C) 2004 by Martin Witte
|
||
|
email : witte@kawo1.rwth-aachen.de
|
||
|
***************************************************************************/
|
||
|
|
||
|
/***************************************************************************
|
||
|
* *
|
||
|
* 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. *
|
||
|
* *
|
||
|
***************************************************************************/
|
||
|
|
||
|
#include "include/soundformat.h"
|
||
|
|
||
|
int SoundFormat::sampleSize() const
|
||
|
{
|
||
|
if (m_SampleBits <= 8) return 1;
|
||
|
if (m_SampleBits <= 16) return 2;
|
||
|
if (m_SampleBits <= 32) return 4;
|
||
|
|
||
|
// unknown
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
|
||
|
int SoundFormat::frameSize() const
|
||
|
{
|
||
|
return sampleSize() * m_Channels;
|
||
|
}
|
||
|
|
||
|
|
||
|
int SoundFormat::minValue() const
|
||
|
{
|
||
|
if (!m_IsSigned) return 0;
|
||
|
return -(1 << (m_SampleBits - 1));
|
||
|
}
|
||
|
|
||
|
|
||
|
int SoundFormat::maxValue() const
|
||
|
{
|
||
|
return (1 << (m_SampleBits - m_IsSigned)) - 1;
|
||
|
}
|
||
|
|
||
|
|
||
12 years ago
|
void SoundFormat::restoreConfig(const TQString &prefix, TDEConfig *c)
|
||
15 years ago
|
{
|
||
|
m_SampleBits = c->readNumEntry (prefix + "bits", 16);
|
||
|
m_IsSigned = c->readBoolEntry(prefix + "sign", true);
|
||
|
m_Channels = c->readNumEntry (prefix + "channels", 2);
|
||
|
m_SampleRate = c->readNumEntry (prefix + "samplerate", 44100);
|
||
|
bool littleEndian = c->readBoolEntry(prefix + "littleEndian", true);
|
||
|
m_Endianess = littleEndian ? LITTLE_ENDIAN : BIG_ENDIAN;
|
||
|
m_Encoding = c->readEntry(prefix + "encoding", "raw");
|
||
|
}
|
||
|
|
||
|
|
||
12 years ago
|
void SoundFormat::saveConfig(const TQString &prefix, TDEConfig *c) const
|
||
15 years ago
|
{
|
||
|
c->writeEntry(prefix + "bits", m_SampleBits);
|
||
|
c->writeEntry(prefix + "sign", m_IsSigned);
|
||
|
c->writeEntry(prefix + "channels", m_Channels);
|
||
|
c->writeEntry(prefix + "samplerate", m_SampleRate);
|
||
|
c->writeEntry(prefix + "littleEndian", m_Endianess == LITTLE_ENDIAN);
|
||
|
c->writeEntry(prefix + "encoding", m_Encoding);
|
||
|
}
|
||
|
|
||
|
|
||
|
int SoundFormat::convertSampleToInt(const char *sample, bool do_scale) const
|
||
|
{
|
||
|
int size = sampleSize();
|
||
|
|
||
|
unsigned val = 0;
|
||
|
if (m_Endianess == LITTLE_ENDIAN) {
|
||
|
sample = sample + size - 1;
|
||
|
for (int i = size - 1; i >= 0; --i, --sample) {
|
||
|
val = (val << 8) | (unsigned char)*sample;
|
||
|
}
|
||
|
} else {
|
||
|
for (int i = 0; i < size; ++i, ++sample) {
|
||
|
val = (val << 8) | (unsigned char)*sample;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int scale = (sizeof(unsigned) << 3) - m_SampleBits;
|
||
13 years ago
|
int signmask = do_scale ? (!m_IsSigned << ((sizeof(unsigned) << 3) - 1)) :
|
||
15 years ago
|
(-m_IsSigned << ((size << 3) - 1)) ;
|
||
|
if (do_scale) {
|
||
|
// map to int number space
|
||
13 years ago
|
return (val << scale) ^ signmask;
|
||
15 years ago
|
} else {
|
||
|
// do only sign extension
|
||
13 years ago
|
if (val & signmask)
|
||
|
val |= signmask;
|
||
15 years ago
|
return val;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void SoundFormat::convertIntToSample(int src, char *dst, bool is_scaled) const
|
||
|
{
|
||
|
int size = sampleSize();
|
||
|
int scale = (sizeof(unsigned) * 8) - m_SampleBits;
|
||
13 years ago
|
int signmask = (!m_IsSigned << (sizeof(unsigned) * 8 - 1));
|
||
15 years ago
|
|
||
13 years ago
|
unsigned val = is_scaled ? (src ^ signmask) >> scale : src;
|
||
15 years ago
|
if (m_Endianess == LITTLE_ENDIAN) {
|
||
|
for (int i = 0; i < size; ++i, ++dst) {
|
||
|
(unsigned char &)*dst = val & 0xFF;
|
||
|
val >>= 8;
|
||
|
}
|
||
|
} else {
|
||
|
dst = dst - 1 + size;
|
||
|
for (int i = size - 1; i >= 0; --i, --dst) {
|
||
|
(unsigned char &)*dst = val & 0xFF;
|
||
|
val >>= 8;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void SoundFormat::convertSamplesToInts(const char *src, int *dst, size_t n, bool do_scale) const
|
||
|
{
|
||
|
int size = sampleSize();
|
||
|
int scale = (sizeof(unsigned) * 8) - m_SampleBits;
|
||
13 years ago
|
int signmask = do_scale ? (!m_IsSigned << ((sizeof(unsigned) << 3) - 1)) :
|
||
15 years ago
|
(-m_IsSigned << ((size << 3) - 1)) ;
|
||
|
if (m_Endianess == LITTLE_ENDIAN) {
|
||
|
src = src - 1 + (size * n);
|
||
|
int *end = dst;
|
||
|
for (dst = dst - 1 + n; dst >= end; --dst) {
|
||
|
unsigned val = 0;
|
||
|
for (int i = size - 1; i >= 0; --i, --src) {
|
||
|
val = (val << 8) | (unsigned char)*src;
|
||
|
}
|
||
|
if (do_scale) {
|
||
13 years ago
|
*dst = (val << scale) ^ signmask;
|
||
|
} else if (val & signmask) {
|
||
|
*dst = val | signmask;
|
||
15 years ago
|
}
|
||
|
}
|
||
|
} else {
|
||
|
for (int *end = dst + n; dst < end; ++dst) {
|
||
|
unsigned val = 0;
|
||
|
for (int i = 0; i < size; ++i, ++src) {
|
||
|
val = (val << 8) | (unsigned char)*src;
|
||
|
}
|
||
|
if (do_scale) {
|
||
13 years ago
|
*dst = (val << scale) ^ signmask;
|
||
|
} else if (val & signmask) {
|
||
|
*dst = val | signmask;
|
||
15 years ago
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void SoundFormat::convertIntsToSamples(const int *src, char *dst, size_t n, bool is_scaled) const
|
||
|
{
|
||
|
int size = sampleSize();
|
||
|
int scale = (sizeof(unsigned) * 8) - m_SampleBits;
|
||
13 years ago
|
int signmask = (!m_IsSigned << (sizeof(unsigned) * 8 - 1));
|
||
15 years ago
|
|
||
|
if (m_Endianess == LITTLE_ENDIAN) {
|
||
|
for (const int *end = src+n; src < end; ++src) {
|
||
13 years ago
|
unsigned val = is_scaled ? ((unsigned)(*src ^ signmask)) >> scale : *src;
|
||
15 years ago
|
for (int i = 0; i < size; ++i, ++dst) {
|
||
|
(unsigned char &)*dst = val & 0xFF;
|
||
|
val >>= 8;
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
dst = dst - 1 + (size * n);
|
||
|
const int *end = src;
|
||
|
for (src = src - 1 + n; src >= end; --src) {
|
||
13 years ago
|
unsigned val = is_scaled ? ((unsigned)(*src ^ signmask)) >> scale : *src;
|
||
15 years ago
|
for (int i = size - 1; i >= 0; --i, --dst) {
|
||
|
(unsigned char &)*dst = val & 0xFF;
|
||
|
val >>= 8;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void SoundFormat::convertSamplesToFloat(const char *_src, float **_dst, size_t n) const
|
||
|
{
|
||
|
int sample_size = sampleSize();
|
||
|
int frame_size = frameSize();
|
||
|
int scale = (sizeof(short) << 3) - m_SampleBits;
|
||
13 years ago
|
int signmask = !m_IsSigned << ((sizeof(short) << 3) - 1);
|
||
15 years ago
|
int skip = frame_size - sample_size;
|
||
|
|
||
|
if (m_Endianess == LITTLE_ENDIAN) {
|
||
|
const char *src_ch0_end = _src + frame_size * (n - 1) + sample_size - 1;
|
||
|
for (unsigned ch = 0; ch < m_Channels; ++ch) {
|
||
|
const char *src = src_ch0_end + sample_size * ch;
|
||
|
float *dst = _dst[ch];
|
||
|
float *end = dst;
|
||
|
for (dst = dst - 1 + n; dst >= end; --dst) {
|
||
|
unsigned val = 0;
|
||
|
for (int i = sample_size - 1; i >= 0; --i, --src) {
|
||
|
val = (val << 8) | (unsigned char)*src;
|
||
|
}
|
||
13 years ago
|
*dst = (float)(signed short)((val << scale) ^ signmask) / 32768.0f;
|
||
15 years ago
|
src = src - skip;
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
for (unsigned ch = 0; ch < m_Channels; ++ch) {
|
||
|
const char *src = _src + sample_size * ch;
|
||
|
float *dst = _dst[ch];
|
||
|
for (float *end = dst + n; dst < end; ++dst) {
|
||
|
unsigned val = 0;
|
||
|
for (int i = 0; i < sample_size; ++i, ++src) {
|
||
|
val = (val << 8) | (unsigned char)*src;
|
||
|
}
|
||
13 years ago
|
*dst = (float)(signed short)((val << scale) ^ signmask) / 32768.0f;
|
||
15 years ago
|
src = src + skip;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void SoundFormat::convertFloatsToSamples(const float **_src, char *_dst, size_t n) const
|
||
|
{
|
||
|
int sample_size = sampleSize();
|
||
|
int frame_size = frameSize();
|
||
|
int scale = (sizeof(short) << 3) - m_SampleBits;
|
||
13 years ago
|
int signmask = (!m_IsSigned << (sizeof(short) << 3) - 1);
|
||
15 years ago
|
int skip = frame_size - sample_size;
|
||
|
|
||
|
if (m_Endianess == LITTLE_ENDIAN) {
|
||
|
for (unsigned ch = 0; ch < m_Channels; ++ch) {
|
||
|
const float *src = _src[ch];
|
||
|
char *dst = _dst + ch * sample_size;
|
||
|
for (const float *end = src+n; src < end; ++src) {
|
||
13 years ago
|
unsigned val = (( ((unsigned)(*src * 32768.0f)) ^ signmask)) >> scale;
|
||
15 years ago
|
for (int i = 0; i < sample_size; ++i, ++dst) {
|
||
|
(unsigned char &)*dst = val & 0xFF;
|
||
|
val >>= 8;
|
||
|
}
|
||
|
dst = dst + skip;
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
char *dst_ch0_end = _dst + frame_size * (n - 1) + sample_size - 1;
|
||
|
for (unsigned ch = 0; ch < m_Channels; ++ch) {
|
||
|
char *dst = dst_ch0_end + sample_size * ch;
|
||
|
const float *src = _src[ch];
|
||
|
const float *end = src;
|
||
|
for (src = src - 1 + n; src >= end; --src) {
|
||
13 years ago
|
unsigned val = (( ((unsigned)(*src * 32768.0f)) ^ signmask)) >> scale;
|
||
15 years ago
|
for (int i = sample_size - 1; i >= 0; --i, --dst) {
|
||
|
(unsigned char &)*dst = val & 0xFF;
|
||
|
val >>= 8;
|
||
|
}
|
||
|
dst = dst - skip;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|