1 #include "audiographer/general/sample_format_converter.h"
3 #include "audiographer/exception.h"
4 #include "audiographer/type_utils.h"
5 #include "private/gdither/gdither.h"
7 #include <boost/format.hpp>
12 template <typename TOut>
13 SampleFormatConverter<TOut>::SampleFormatConverter (ChannelCount channels) :
24 SampleFormatConverter<float>::init (framecnt_t max_frames, int /* type */, int data_width)
26 if (throw_level (ThrowObject) && data_width != 32) {
27 throw Exception (*this, "Unsupported data width");
29 init_common (max_frames);
30 dither = gdither_new (GDitherNone, channels, GDitherFloat, data_width);
35 SampleFormatConverter<int32_t>::init (framecnt_t max_frames, int type, int data_width)
37 if(throw_level (ThrowObject) && data_width < 24) {
38 throw Exception (*this, "Trying to use SampleFormatConverter<int32_t> for data widths < 24");
41 init_common (max_frames);
43 if (data_width == 24) {
44 dither = gdither_new ((GDitherType) type, channels, GDither32bit, data_width);
45 } else if (data_width == 32) {
46 dither = gdither_new (GDitherNone, channels, GDitherFloat, data_width);
47 } else if (throw_level (ThrowObject)) {
48 throw Exception (*this, "Unsupported data width");
54 SampleFormatConverter<int16_t>::init (framecnt_t max_frames, int type, int data_width)
56 if (throw_level (ThrowObject) && data_width != 16) {
57 throw Exception (*this, "Unsupported data width");
59 init_common (max_frames);
60 dither = gdither_new ((GDitherType) type, channels, GDither16bit, data_width);
65 SampleFormatConverter<uint8_t>::init (framecnt_t max_frames, int type, int data_width)
67 if (throw_level (ThrowObject) && data_width != 8) {
68 throw Exception (*this, "Unsupported data width");
70 init_common (max_frames);
71 dither = gdither_new ((GDitherType) type, channels, GDither8bit, data_width);
74 template <typename TOut>
76 SampleFormatConverter<TOut>::init_common (framecnt_t max_frames)
79 if (max_frames > data_out_size) {
83 data_out = new TOut[max_frames];
84 data_out_size = max_frames;
88 template <typename TOut>
89 SampleFormatConverter<TOut>::~SampleFormatConverter ()
94 template <typename TOut>
96 SampleFormatConverter<TOut>::reset()
99 gdither_free (dither);
110 /* Basic const version of process() */
111 template <typename TOut>
113 SampleFormatConverter<TOut>::process (ProcessContext<float> const & c_in)
115 float const * const data = c_in.data();
117 check_frame_and_channel_count (c_in.frames (), c_in.channels ());
121 for (uint32_t chn = 0; chn < c_in.channels(); ++chn) {
122 gdither_runf (dither, chn, c_in.frames_per_channel (), data, data_out);
127 ProcessContext<TOut> c_out(c_in, data_out);
131 /* Basic non-const version of process(), calls the const one */
132 template<typename TOut>
134 SampleFormatConverter<TOut>::process (ProcessContext<float> & c_in)
136 process (static_cast<ProcessContext<float> const &> (c_in));
139 /* template specialization for float, in-place processing (non-const) */
142 SampleFormatConverter<float>::process (ProcessContext<float> & c_in)
144 framecnt_t frames = c_in.frames();
145 float * data = c_in.data();
148 for (framecnt_t x = 0; x < frames; ++x) {
149 if (data[x] > 1.0f) {
151 } else if (data[x] < -1.0f) {
160 /* template specialized const version, copies the data, and calls the non-const version */
163 SampleFormatConverter<float>::process (ProcessContext<float> const & c_in)
165 // Make copy of data and pass it to non-const version
166 check_frame_and_channel_count (c_in.frames(), c_in.channels());
167 TypeUtils<float>::copy (c_in.data(), data_out, c_in.frames());
169 ProcessContext<float> c (c_in, data_out);
173 template<typename TOut>
175 SampleFormatConverter<TOut>::check_frame_and_channel_count (framecnt_t frames, ChannelCount channels_)
177 if (throw_level (ThrowStrict) && channels_ != channels) {
178 throw Exception (*this, boost::str (boost::format
179 ("Wrong channel count given to process(), %1% instead of %2%")
180 % channels_ % channels));
183 if (throw_level (ThrowProcess) && frames > data_out_size) {
184 throw Exception (*this, boost::str (boost::format
185 ("Too many frames given to process(), %1% instad of %2%")
186 % frames % data_out_size));
190 template class SampleFormatConverter<uint8_t>;
191 template class SampleFormatConverter<int16_t>;
192 template class SampleFormatConverter<int32_t>;
193 template class SampleFormatConverter<float>;