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: setUp()21 void setUp() 22 { 23 samples = 128; 24 random_data = TestUtils::init_random_data(samples, 1.0); 25 } 26 tearDown()27 void tearDown() 28 { 29 delete [] random_data; 30 } 31 testInit()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 (samples, D_Tri, 32); // Doesn't throw 37 CPPUNIT_ASSERT_THROW (f_converter->init (samples, D_Tri, 24), Exception); 38 CPPUNIT_ASSERT_THROW (f_converter->init (samples, 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 (samples, D_Tri, 32); // Doesn't throw 45 i_converter->init (samples, D_Tri, 24); // Doesn't throw 46 i_converter->init (samples, D_Tri, 8); // Doesn't throw 47 i_converter->init (samples, D_Tri, 16); // Doesn't throw 48 CPPUNIT_ASSERT_THROW (i_converter->init (samples, D_Tri, 48), Exception); 49 50 boost::shared_ptr<SampleFormatConverter<int16_t> > i16_converter (new SampleFormatConverter<int16_t>(1)); 51 i16_converter->init (samples, D_Tri, 16); // Doesn't throw 52 i16_converter->init (samples, D_Tri, 8); // Doesn't throw 53 CPPUNIT_ASSERT_THROW (i16_converter->init (samples, D_Tri, 32), Exception); 54 CPPUNIT_ASSERT_THROW (i16_converter->init (samples, D_Tri, 48), Exception); 55 56 boost::shared_ptr<SampleFormatConverter<uint8_t> > ui_converter (new SampleFormatConverter<uint8_t>(1)); 57 ui_converter->init (samples, D_Tri, 8); // Doesn't throw 58 ui_converter->init (samples, D_Tri, 4); // Doesn't throw 59 CPPUNIT_ASSERT_THROW (ui_converter->init (samples, D_Tri, 16), Exception); 60 } 61 testFrameCount()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 (samples, D_Tri, 32); 68 converter->add_output (sink); 69 samplecnt_t samples_output = 0; 70 71 { 72 ProcessContext<float> pc(random_data, samples / 2, 1); 73 converter->process (pc); 74 samples_output = sink->get_data().size(); 75 CPPUNIT_ASSERT_EQUAL (samples / 2, samples_output); 76 } 77 78 { 79 ProcessContext<float> pc(random_data, samples, 1); 80 converter->process (pc); 81 samples_output = sink->get_data().size(); 82 CPPUNIT_ASSERT_EQUAL (samples, samples_output); 83 } 84 85 { 86 ProcessContext<float> pc(random_data, samples + 1, 1); 87 CPPUNIT_ASSERT_THROW(converter->process (pc), Exception); 88 } 89 } 90 testFloat()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 samplecnt_t samples_output = 0; 96 97 converter->init(samples, D_Tri, 32); 98 converter->add_output (sink); 99 100 converter->set_clip_floats (false); 101 ProcessContext<float> const pc(random_data, samples, 1); 102 converter->process (pc); 103 samples_output = sink->get_data().size(); 104 CPPUNIT_ASSERT_EQUAL (samples, samples_output); 105 CPPUNIT_ASSERT (TestUtils::array_equals(sink->get_array(), random_data, samples)); 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 samples_output = sink->get_data().size(); 114 CPPUNIT_ASSERT_EQUAL (samples, samples_output); 115 CPPUNIT_ASSERT (TestUtils::array_filled(sink->get_array(), samples)); 116 117 for (samplecnt_t i = 0; i < samples; ++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 testInt32()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 samplecnt_t samples_output = 0; 129 130 converter->init(samples, D_Tri, 32); 131 converter->add_output (sink); 132 133 ProcessContext<float> pc(random_data, samples, 1); 134 converter->process (pc); 135 samples_output = sink->get_data().size(); 136 CPPUNIT_ASSERT_EQUAL (samples, samples_output); 137 CPPUNIT_ASSERT (TestUtils::array_filled(sink->get_array(), samples)); 138 } 139 testInt24()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 samplecnt_t samples_output = 0; 145 146 converter->init(samples, D_Tri, 24); 147 converter->add_output (sink); 148 149 ProcessContext<float> pc(random_data, samples, 1); 150 converter->process (pc); 151 samples_output = sink->get_data().size(); 152 CPPUNIT_ASSERT_EQUAL (samples, samples_output); 153 CPPUNIT_ASSERT (TestUtils::array_filled(sink->get_array(), samples)); 154 } 155 testInt16()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 samplecnt_t samples_output = 0; 161 162 converter->init(samples, D_Tri, 16); 163 converter->add_output (sink); 164 165 ProcessContext<float> pc(random_data, samples, 1); 166 converter->process (pc); 167 samples_output = sink->get_data().size(); 168 CPPUNIT_ASSERT_EQUAL (samples, samples_output); 169 CPPUNIT_ASSERT (TestUtils::array_filled(sink->get_array(), samples)); 170 } 171 testUint8()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 samplecnt_t samples_output = 0; 177 178 converter->init(samples, D_Tri, 8); 179 converter->add_output (sink); 180 181 ProcessContext<float> pc(random_data, samples, 1); 182 converter->process (pc); 183 samples_output = sink->get_data().size(); 184 CPPUNIT_ASSERT_EQUAL (samples, samples_output); 185 CPPUNIT_ASSERT (TestUtils::array_filled(sink->get_array(), samples)); 186 } 187 testChannelCount()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 samplecnt_t samples_output = 0; 193 194 converter->init(samples, 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 samplecnt_t new_sample_count = samples - (samples % 3); 201 converter->process (ProcessContext<float> (pc.data(), new_sample_count, 3)); 202 samples_output = sink->get_data().size(); 203 CPPUNIT_ASSERT_EQUAL (new_sample_count, samples_output); 204 CPPUNIT_ASSERT (TestUtils::array_filled(sink->get_array(), pc.samples())); 205 } 206 207 private: 208 209 float * random_data; 210 samplecnt_t samples; 211 }; 212 213 CPPUNIT_TEST_SUITE_REGISTRATION (SampleFormatConverterTest); 214 215