977e2b390a9d034c38c2a5228bd94f63b70d00c8
[ardour.git] / libs / audiographer / tests / general / sample_format_converter_test.cc
1 #include "tests/utils.h"
2
3 #include "audiographer/general/sample_format_converter.h"
4
5 using namespace AudioGrapher;
6
7 class SampleFormatConverterTest : public CppUnit::TestFixture
8 {
9   CPPUNIT_TEST_SUITE (SampleFormatConverterTest);
10   CPPUNIT_TEST (testInit);
11   CPPUNIT_TEST (testFrameCount);
12   CPPUNIT_TEST (testFloat);
13   CPPUNIT_TEST (testInt32);
14   CPPUNIT_TEST (testInt24);
15   CPPUNIT_TEST (testInt16);
16   CPPUNIT_TEST (testUint8);
17   CPPUNIT_TEST (testChannelCount);
18   CPPUNIT_TEST_SUITE_END ();
19
20   public:
21         void setUp()
22         {
23                 frames = 128;
24                 random_data = TestUtils::init_random_data(frames, 1.0);
25         }
26
27         void tearDown()
28         {
29                 delete [] random_data;
30         }
31
32         void testInit()
33         {
34                 // Float never uses dithering and should always use full 32 bits of data
35                 boost::shared_ptr<SampleFormatConverter<float> > f_converter (new SampleFormatConverter<float>(1));
36                 f_converter->init (frames, D_Tri, 32); // Doesn't throw
37                 CPPUNIT_ASSERT_THROW (f_converter->init (frames, D_Tri, 24), Exception);
38                 CPPUNIT_ASSERT_THROW (f_converter->init (frames, D_Tri, 48), Exception);
39
40                 /* Test that too large data widths throw.
41                    We are fine with unnecessarily narrow data widths */
42
43                 boost::shared_ptr<SampleFormatConverter<int32_t> > i_converter (new SampleFormatConverter<int32_t>(1));
44                 i_converter->init (frames, D_Tri, 32); // Doesn't throw
45                 i_converter->init (frames, D_Tri, 24); // Doesn't throw
46                 i_converter->init (frames, D_Tri, 8); // Doesn't throw
47                 i_converter->init (frames, D_Tri, 16); // Doesn't throw
48                 CPPUNIT_ASSERT_THROW (i_converter->init (frames, D_Tri, 48), Exception);
49
50                 boost::shared_ptr<SampleFormatConverter<int16_t> > i16_converter (new SampleFormatConverter<int16_t>(1));
51                 i16_converter->init (frames, D_Tri, 16); // Doesn't throw
52                 i16_converter->init (frames, D_Tri, 8); // Doesn't throw
53                 CPPUNIT_ASSERT_THROW (i16_converter->init (frames, D_Tri, 32), Exception);
54                 CPPUNIT_ASSERT_THROW (i16_converter->init (frames, D_Tri, 48), Exception);
55
56                 boost::shared_ptr<SampleFormatConverter<uint8_t> > ui_converter (new SampleFormatConverter<uint8_t>(1));
57                 ui_converter->init (frames, D_Tri, 8); // Doesn't throw
58                 ui_converter->init (frames, D_Tri, 4); // Doesn't throw
59                 CPPUNIT_ASSERT_THROW (ui_converter->init (frames, D_Tri, 16), Exception);
60         }
61
62         void testFrameCount()
63         {
64                 boost::shared_ptr<SampleFormatConverter<int32_t> > converter (new SampleFormatConverter<int32_t>(1));
65                 boost::shared_ptr<VectorSink<int32_t> > sink (new VectorSink<int32_t>());
66                 
67                 converter->init (frames, D_Tri, 32);
68                 converter->add_output (sink);
69                 framecnt_t frames_output = 0;
70                 
71                 {
72                 ProcessContext<float> pc(random_data, frames / 2, 1);
73                 converter->process (pc);
74                 frames_output = sink->get_data().size();
75                 CPPUNIT_ASSERT_EQUAL (frames / 2, frames_output);
76                 }
77                 
78                 {
79                 ProcessContext<float> pc(random_data, frames, 1);
80                 converter->process (pc);
81                 frames_output = sink->get_data().size();
82                 CPPUNIT_ASSERT_EQUAL (frames, frames_output);
83                 }
84                 
85                 {
86                 ProcessContext<float> pc(random_data, frames + 1, 1);
87                 CPPUNIT_ASSERT_THROW(converter->process (pc), Exception);
88                 }
89         }
90
91         void testFloat()
92         {
93                 boost::shared_ptr<SampleFormatConverter<float> > converter (new SampleFormatConverter<float>(1));
94                 boost::shared_ptr<VectorSink<float> > sink (new VectorSink<float>());
95                 framecnt_t frames_output = 0;
96                 
97                 converter->init(frames, D_Tri, 32);
98                 converter->add_output (sink);
99                 
100                 converter->set_clip_floats (false);
101                 ProcessContext<float> const pc(random_data, frames, 1);
102                 converter->process (pc);
103                 frames_output = sink->get_data().size();
104                 CPPUNIT_ASSERT_EQUAL (frames, frames_output);
105                 CPPUNIT_ASSERT (TestUtils::array_equals(sink->get_array(), random_data, frames));
106                 
107                 // Make sure a few samples are < -1.0 and > 1.0
108                 random_data[10] = -1.5;
109                 random_data[20] = 1.5;
110                 
111                 converter->set_clip_floats (true);
112                 converter->process (pc);
113                 frames_output = sink->get_data().size();
114                 CPPUNIT_ASSERT_EQUAL (frames, frames_output);
115                 CPPUNIT_ASSERT (TestUtils::array_filled(sink->get_array(), frames));
116                 
117                 for (framecnt_t i = 0; i < frames; ++i) {
118                         // fp comparison needs a bit of tolerance, 1.01 << 1.5
119                         CPPUNIT_ASSERT(sink->get_data()[i] < 1.01);
120                         CPPUNIT_ASSERT(sink->get_data()[i] > -1.01);
121                 }
122         }
123
124         void testInt32()
125         {
126                 boost::shared_ptr<SampleFormatConverter<int32_t> > converter (new SampleFormatConverter<int32_t>(1));
127                 boost::shared_ptr<VectorSink<int32_t> > sink (new VectorSink<int32_t>());
128                 framecnt_t frames_output = 0;
129                 
130                 converter->init(frames, D_Tri, 32);
131                 converter->add_output (sink);
132                 
133                 ProcessContext<float> pc(random_data, frames, 1);
134                 converter->process (pc);
135                 frames_output = sink->get_data().size();
136                 CPPUNIT_ASSERT_EQUAL (frames, frames_output);
137                 CPPUNIT_ASSERT (TestUtils::array_filled(sink->get_array(), frames));
138         }
139         
140         void testInt24()
141         {
142                 boost::shared_ptr<SampleFormatConverter<int32_t> > converter (new SampleFormatConverter<int32_t>(1));
143                 boost::shared_ptr<VectorSink<int32_t> > sink (new VectorSink<int32_t>());
144                 framecnt_t frames_output = 0;
145                 
146                 converter->init(frames, D_Tri, 24);
147                 converter->add_output (sink);
148                 
149                 ProcessContext<float> pc(random_data, frames, 1);
150                 converter->process (pc);
151                 frames_output = sink->get_data().size();
152                 CPPUNIT_ASSERT_EQUAL (frames, frames_output);
153                 CPPUNIT_ASSERT (TestUtils::array_filled(sink->get_array(), frames));
154         }
155         
156         void testInt16()
157         {
158                 boost::shared_ptr<SampleFormatConverter<int16_t> > converter (new SampleFormatConverter<int16_t>(1));
159                 boost::shared_ptr<VectorSink<int16_t> > sink (new VectorSink<int16_t>());
160                 framecnt_t frames_output = 0;
161                 
162                 converter->init(frames, D_Tri, 16);
163                 converter->add_output (sink);
164                 
165                 ProcessContext<float> pc(random_data, frames, 1);
166                 converter->process (pc);
167                 frames_output = sink->get_data().size();
168                 CPPUNIT_ASSERT_EQUAL (frames, frames_output);
169                 CPPUNIT_ASSERT (TestUtils::array_filled(sink->get_array(), frames));
170         }
171         
172         void testUint8()
173         {
174                 boost::shared_ptr<SampleFormatConverter<uint8_t> > converter (new SampleFormatConverter<uint8_t>(1));
175                 boost::shared_ptr<VectorSink<uint8_t> > sink (new VectorSink<uint8_t>());
176                 framecnt_t frames_output = 0;
177                 
178                 converter->init(frames, D_Tri, 8);
179                 converter->add_output (sink);
180                 
181                 ProcessContext<float> pc(random_data, frames, 1);
182                 converter->process (pc);
183                 frames_output = sink->get_data().size();
184                 CPPUNIT_ASSERT_EQUAL (frames, frames_output);
185                 CPPUNIT_ASSERT (TestUtils::array_filled(sink->get_array(), frames));
186         }
187         
188         void testChannelCount()
189         {
190                 boost::shared_ptr<SampleFormatConverter<int32_t> > converter (new SampleFormatConverter<int32_t>(3));
191                 boost::shared_ptr<VectorSink<int32_t> > sink (new VectorSink<int32_t>());
192                 framecnt_t frames_output = 0;
193                 
194                 converter->init(frames, D_Tri, 32);
195                 converter->add_output (sink);
196                 
197                 ProcessContext<float> pc(random_data, 4, 1);
198                 CPPUNIT_ASSERT_THROW (converter->process (pc), Exception);
199                 
200                 framecnt_t new_frame_count = frames - (frames % 3);
201                 converter->process (ProcessContext<float> (pc.data(), new_frame_count, 3));
202                 frames_output = sink->get_data().size();
203                 CPPUNIT_ASSERT_EQUAL (new_frame_count, frames_output);
204                 CPPUNIT_ASSERT (TestUtils::array_filled(sink->get_array(), pc.frames()));
205         }
206
207   private:
208
209         float * random_data;
210         framecnt_t frames;
211 };
212
213 CPPUNIT_TEST_SUITE_REGISTRATION (SampleFormatConverterTest);
214