kwave  18.07.70
SampleDecoderLinear.cpp
Go to the documentation of this file.
1 /*************************************************************************
2  SampleDecoderLinear.cpp - decoder for all non-compressed linear formats
3  -------------------
4  begin : Sat Nov 01 2003
5  copyright : (C) 2003 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 
22 #include <QtGlobal>
23 
24 #include "libkwave/Sample.h"
25 #include "libkwave/SampleFormat.h"
26 #include "libkwave/Utils.h"
27 
28 #include "SampleDecoderLinear.h"
29 
30 //***************************************************************************
31 static void decode_NULL(const quint8 *src, sample_t *dst, unsigned int count)
32 {
33  while (count--) {
34  printf("%02X ", Kwave::toInt(*src));
35  *(dst++) = count % (1 << (SAMPLE_BITS-1));
36  }
37 }
38 
39 //***************************************************************************
40 // this little function is provided as inline code to avaid a compiler
41 // warning about negative shift value when included directly
42 static inline quint32 shl(const quint32 v, const int s)
43 {
44  if (!s)
45  return v;
46  else if (s > 0)
47  return (v << s);
48  else
49  return (v >> (-s));
50 }
51 
52 //***************************************************************************
61 template<const unsigned int bits, const bool is_signed,
62  const bool is_little_endian>
63 void decode_linear(const quint8 *src, sample_t *dst, unsigned int count)
64 {
65  const int shift = (SAMPLE_BITS - bits);
66  const quint32 sign = 1 << (SAMPLE_BITS-1);
67  const quint32 negative = ~(sign - 1);
68  const quint32 bytes = (bits+7) >> 3;
69 
70  while (count) {
71  count--;
72 
73  // read from source buffer
74  quint32 s = 0;
75  if (is_little_endian) {
76  // little endian
77  for (unsigned int byte = 0; byte < bytes; ++byte, ++src) {
78  s |= static_cast<quint8>(*src) << (byte << 3);
79  }
80  } else {
81  // big endian
82  for (int byte = bytes - 1; byte >= 0; --byte, ++src) {
83  s |= static_cast<quint8>(*src) << (byte << 3);
84  }
85  }
86 
87  // convert to signed
88  if (!is_signed) s -= shl(1, bits-1)-1;
89 
90  // shift up to Kwave's bit count
91  s = shl(s, shift);
92 
93  // sign correcture for negative values
94  if (is_signed && (s & sign)) s |= negative;
95 
96  // write to destination buffer
97  *(dst++) = static_cast<sample_t>(s);
98  }
99 }
100 
101 //***************************************************************************
102 #define MAKE_DECODER(bits) \
103 if (sample_format != Kwave::SampleFormat::Unsigned) { \
104  if (endianness != Kwave::BigEndian) { \
105  m_decoder = decode_linear<bits, true, true>; \
106  } else { \
107  m_decoder = decode_linear<bits, true, false>; \
108  } \
109 } else { \
110  if (endianness != Kwave::BigEndian) { \
111  m_decoder = decode_linear<bits, false, true>; \
112  } else { \
113  m_decoder = decode_linear<bits, false, false>; \
114  } \
115 }
116 
117 //***************************************************************************
119  Kwave::SampleFormat::Format sample_format,
120  unsigned int bits_per_sample,
121  Kwave::byte_order_t endianness
122 )
123  :Kwave::SampleDecoder(),
124  m_bytes_per_sample((bits_per_sample + 7) >> 3),
125  m_decoder(decode_NULL)
126 {
127  // sanity checks: we support only signed/unsigned and big/little endian
128  Q_ASSERT((sample_format == Kwave::SampleFormat::Signed) ||
129  (sample_format == Kwave::SampleFormat::Unsigned));
130  if ((sample_format != Kwave::SampleFormat::Signed) &&
131  (sample_format != Kwave::SampleFormat::Unsigned)) return;
132 
133  // allow unknown endianness only with 8 bits
134  Q_ASSERT((endianness != Kwave::UnknownEndian) || (m_bytes_per_sample == 1));
135  if ((endianness == Kwave::UnknownEndian) &&
136  (m_bytes_per_sample != 1)) return;
137 
138  // map cpu endianness to little or big
139 #if Q_BYTE_ORDER == Q_BIG_ENDIAN
140  if (endianness == Kwave::CpuEndian) endianness = Kwave::BigEndian;
141 #else
142  if (endianness == Kwave::CpuEndian) endianness = Kwave::LittleEndian;
143 #endif
144 
145  switch (m_bytes_per_sample) {
146  case 1:
147  MAKE_DECODER(8);
148  break;
149  case 2:
150  MAKE_DECODER(16);
151  break;
152  case 3:
153  MAKE_DECODER(24);
154  break;
155  case 4:
156  MAKE_DECODER(32);
157  break;
158  }
159 }
160 
161 //***************************************************************************
163 {
164 }
165 
166 //***************************************************************************
167 void Kwave::SampleDecoderLinear::decode(QByteArray &raw_data,
168  Kwave::SampleArray &decoded)
169 {
170  Q_ASSERT(m_decoder);
171  if (!m_decoder) return;
172 
173  unsigned int samples = raw_data.size() / m_bytes_per_sample;
174  const quint8 *src = reinterpret_cast<const quint8 *>(raw_data.constData());
175  sample_t *dst = decoded.data();
176 
177  m_decoder(src, dst, samples);
178 }
179 
180 //***************************************************************************
182 {
183  return m_bytes_per_sample;
184 }
185 
186 //***************************************************************************
187 //***************************************************************************
byte_order_t
Definition: ByteOrder.h:25
Definition: App.h:33
void decode_linear(const quint8 *src, sample_t *dst, unsigned int count)
virtual void decode(QByteArray &raw_data, Kwave::SampleArray &decoded) Q_DECL_OVERRIDE
static quint32 shl(const quint32 v, const int s)
int toInt(T x)
Definition: Utils.h:127
#define MAKE_DECODER(bits)
static void decode_NULL(const quint8 *src, sample_t *dst, unsigned int count)
virtual ~SampleDecoderLinear() Q_DECL_OVERRIDE
SampleDecoderLinear(Kwave::SampleFormat::Format sample_format, unsigned int bits_per_sample, Kwave::byte_order_t endianness)
sample_t * data()
Definition: SampleArray.h:62
virtual unsigned int rawBytesPerSample() Q_DECL_OVERRIDE
#define SAMPLE_BITS
Definition: Sample.h:43
void(* m_decoder)(const quint8 *, sample_t *, unsigned int)
qint32 sample_t
Definition: Sample.h:37