kwave  18.07.70
SampleEncoderLinear.cpp
Go to the documentation of this file.
1 /*************************************************************************
2  SampleEncoderLinear.cpp - encoder for all non-compressed linear formats
3  -------------------
4  begin : Tue Apr 18 2006
5  copyright : (C) 2006 by Thomas Eschenbacher
6  email : Thomas.Eschenbacher@gmx.de
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "config.h"
19 
20 #include <stdio.h>
21 #include <sys/types.h>
22 
23 #include <QtGlobal>
24 
25 #include "libkwave/Sample.h"
27 #include "libkwave/SampleFormat.h"
28 #include "libkwave/Utils.h"
29 
30 //***************************************************************************
31 static void encode_NULL(const sample_t *src, quint8 *dst, unsigned int count)
32 {
33  (void)src;
34  (void)dst;
35  (void)count;
36 // qWarning("call to encode_NULL");
37 }
38 
39 //***************************************************************************
48 template<const unsigned int bits, const bool is_signed,
49  const bool is_little_endian>
50 void encode_linear(const sample_t *src, quint8 *dst, unsigned int count)
51 {
52  for ( ; count; --count) {
53  // read from source buffer
54  sample_t s = *(src++);
55 
56  // convert to unsigned if necessary
57  if (!is_signed)
58  s += 1 << (SAMPLE_BITS-1);
59 
60  // shrink 18/20 bits and similar down, otherwise it does not work
61  // with ALSA for some dubious reason !?
62  if (bits == 20)
63  s >>= 4;
64  if (bits == 18) // don't ask me why... !!!???
65  s >>= 6;
66 
67  if (is_little_endian) {
68  // little endian
69  if (bits > 24)
70  *(dst++) = 0x00;
71  if (bits > 16)
72  *(dst++) = static_cast<quint8>(s & 0xFF);
73  if (bits > 8)
74  *(dst++) = static_cast<quint8>(s >> 8);
75  if (bits >= 8)
76  *(dst++) = static_cast<quint8>(s >> 16);
77  } else {
78  // big endian
79  if (bits >= 8)
80  *(dst++) = static_cast<quint8>(s >> 16);
81  if (bits > 8)
82  *(dst++) = static_cast<quint8>(s >> 8);
83  if (bits > 16)
84  *(dst++) = static_cast<quint8>(s & 0xFF);
85  if (bits > 24)
86  *(dst++) = 0x00;
87  }
88  }
89 }
90 
91 //***************************************************************************
92 #define MAKE_ENCODER(bits) \
93 if (sample_format != Kwave::SampleFormat::Unsigned) { \
94  if (endianness != Kwave::BigEndian) { \
95  m_encoder = encode_linear<bits, true, true>; \
96  } else { \
97  m_encoder = encode_linear<bits, true, false>; \
98  } \
99 } else { \
100  if (endianness != Kwave::BigEndian) { \
101  m_encoder = encode_linear<bits, false, true>; \
102  } else { \
103  m_encoder = encode_linear<bits, false, false>; \
104  } \
105 }
106 
107 //***************************************************************************
109  Kwave::SampleFormat::Format sample_format,
110  unsigned int bits_per_sample,
111  Kwave::byte_order_t endianness
112 )
113  :SampleEncoder(),
114  m_bytes_per_sample((bits_per_sample + 7) >> 3),
115  m_encoder(encode_NULL)
116 {
117  // sanity checks: we support only signed/unsigned and big/little endian
118  Q_ASSERT((sample_format == Kwave::SampleFormat::Signed) ||
119  (sample_format == Kwave::SampleFormat::Unsigned));
120  if ((sample_format != Kwave::SampleFormat::Signed) &&
121  (sample_format != Kwave::SampleFormat::Unsigned)) return;
122 
123  // allow unknown endianness only with 8 bits
124  Q_ASSERT((endianness != Kwave::UnknownEndian) || (m_bytes_per_sample == 1));
125  if ( (endianness == Kwave::UnknownEndian) &&
126  (m_bytes_per_sample != 1) ) return;
127 
128  // map cpu endianness to little or big
129 #if Q_BYTE_ORDER == Q_BIG_ENDIAN
130  if (endianness == Kwave::CpuEndian) endianness = Kwave::BigEndian;
131 #else
132  if (endianness == Kwave::CpuEndian) endianness = Kwave::LittleEndian;
133 #endif
134 
135 // qDebug("SampleEncoderLinear::SampleEncoderLinear(fmt=%s, "
136 // "%u bit [%u bytes], endian=%s)",
137 // (sample_format == Kwave::SampleFormat::Signed) ?
138 // "signed" : "unsigned",
139 // bits_per_sample, m_bytes_per_sample,
140 // (endianness == Kwave::BigEndian) ? "BE" : "LE");
141 
142  switch (bits_per_sample) {
143  case 8:
144  MAKE_ENCODER(8);
145  break;
146  case 16:
147  MAKE_ENCODER(16);
148  break;
149  case 18:
150  MAKE_ENCODER(18);
151  break;
152  case 20:
153  MAKE_ENCODER(20);
154  break;
155  case 24:
156  MAKE_ENCODER(24);
157  break;
158  case 32:
159  MAKE_ENCODER(32);
160  break;
161  }
162 
163  Q_ASSERT(m_encoder != encode_NULL);
164 }
165 
166 //***************************************************************************
168 {
169 }
170 
171 //***************************************************************************
173  unsigned int count,
174  QByteArray &raw_data)
175 {
176  Q_ASSERT(m_encoder);
177  if (!m_encoder) return;
178 
179  Q_ASSERT(count * m_bytes_per_sample <= Kwave::toUint(raw_data.size()));
180  if (count * m_bytes_per_sample > Kwave::toUint(raw_data.size())) return;
181 
182  const sample_t *src = samples.constData();
183  quint8 *dst = reinterpret_cast<quint8 *>(raw_data.data());
184 
185  m_encoder(src, dst, count);
186 }
187 
188 //***************************************************************************
190 {
191  return m_bytes_per_sample;
192 }
193 
194 //***************************************************************************
195 //***************************************************************************
virtual ~SampleEncoderLinear() Q_DECL_OVERRIDE
byte_order_t
Definition: ByteOrder.h:25
#define MAKE_ENCODER(bits)
virtual unsigned int rawBytesPerSample() Q_DECL_OVERRIDE
void(* m_encoder)(const sample_t *, quint8 *, unsigned int)
SampleEncoderLinear(Kwave::SampleFormat::Format sample_format, unsigned int bits_per_sample, Kwave::byte_order_t endianness)
virtual void encode(const Kwave::SampleArray &samples, unsigned int count, QByteArray &raw_data) Q_DECL_OVERRIDE
const sample_t * constData() const
Definition: SampleArray.h:54
static void encode_NULL(const sample_t *src, quint8 *dst, unsigned int count)
unsigned int toUint(T x)
Definition: Utils.h:109
void encode_linear(const sample_t *src, quint8 *dst, unsigned int count)
#define SAMPLE_BITS
Definition: Sample.h:43
qint32 sample_t
Definition: Sample.h:37