1 #include "tests/utils.h"
2 
3 #include "audiographer/general/chunker.h"
4 
5 #include <cassert>
6 
7 using namespace AudioGrapher;
8 
9 class ChunkerTest : public CppUnit::TestFixture
10 {
11 	// TODO: Test EndOfInput handling
12 
13   CPPUNIT_TEST_SUITE (ChunkerTest);
14   CPPUNIT_TEST (testSynchronousProcess);
15   CPPUNIT_TEST (testAsynchronousProcess);
16   CPPUNIT_TEST (testChoppingProcess);
17   CPPUNIT_TEST (testEndOfInputFlagHandling);
18   CPPUNIT_TEST_SUITE_END ();
19 
20   public:
setUp()21 	void setUp()
22 	{
23 		samples = 128;
24 		random_data = TestUtils::init_random_data(samples);
25 		sink.reset (new VectorSink<float>());
26 		chunker.reset (new Chunker<float>(samples * 2));
27 	}
28 
tearDown()29 	void tearDown()
30 	{
31 		delete [] random_data;
32 	}
33 
testSynchronousProcess()34 	void testSynchronousProcess()
35 	{
36 		chunker->add_output (sink);
37 		samplecnt_t samples_output = 0;
38 
39 		ProcessContext<float> const context (random_data, samples, 1);
40 
41 		chunker->process (context);
42 		samples_output = sink->get_data().size();
43 		CPPUNIT_ASSERT_EQUAL ((samplecnt_t) 0, samples_output);
44 
45 		chunker->process (context);
46 		samples_output = sink->get_data().size();
47 		CPPUNIT_ASSERT_EQUAL (2 * samples, samples_output);
48 		CPPUNIT_ASSERT (TestUtils::array_equals (random_data, sink->get_array(), samples));
49 		CPPUNIT_ASSERT (TestUtils::array_equals (random_data, &sink->get_array()[samples], samples));
50 
51 		sink->reset();
52 
53 		chunker->process (context);
54 		samples_output = sink->get_data().size();
55 		CPPUNIT_ASSERT_EQUAL ((samplecnt_t) 0, samples_output);
56 
57 		chunker->process (context);
58 		samples_output = sink->get_data().size();
59 		CPPUNIT_ASSERT_EQUAL (2 * samples, samples_output);
60 		CPPUNIT_ASSERT (TestUtils::array_equals (random_data, sink->get_array(), samples));
61 		CPPUNIT_ASSERT (TestUtils::array_equals (random_data, &sink->get_array()[samples], samples));
62 	}
63 
testAsynchronousProcess()64 	void testAsynchronousProcess()
65 	{
66 		assert (samples % 2 == 0);
67 
68 		chunker->add_output (sink);
69 		samplecnt_t samples_output = 0;
70 
71 		ProcessContext<float> const half_context (random_data, samples / 2, 1);
72 		ProcessContext<float> const context (random_data, samples, 1);
73 
74 		// 0.5
75 		chunker->process (half_context);
76 		samples_output = sink->get_data().size();
77 		CPPUNIT_ASSERT_EQUAL ((samplecnt_t) 0, samples_output);
78 
79 		// 1.5
80 		chunker->process (context);
81 		samples_output = sink->get_data().size();
82 		CPPUNIT_ASSERT_EQUAL ((samplecnt_t) 0, samples_output);
83 
84 		// 2.5
85 		chunker->process (context);
86 		samples_output = sink->get_data().size();
87 		CPPUNIT_ASSERT_EQUAL (2 * samples, samples_output);
88 		CPPUNIT_ASSERT (TestUtils::array_equals (random_data, sink->get_array(), samples / 2));
89 		CPPUNIT_ASSERT (TestUtils::array_equals (random_data, &sink->get_array()[samples / 2], samples));
90 		CPPUNIT_ASSERT (TestUtils::array_equals (random_data, &sink->get_array()[ 3 * samples / 2], samples / 2));
91 
92 		sink->reset();
93 
94 		// 3.5
95 		chunker->process (context);
96 		samples_output = sink->get_data().size();
97 		CPPUNIT_ASSERT_EQUAL ((samplecnt_t) 0, samples_output);
98 
99 		// 4.0
100 		chunker->process (half_context);
101 		samples_output = sink->get_data().size();
102 		CPPUNIT_ASSERT_EQUAL (2 * samples, samples_output);
103 		CPPUNIT_ASSERT (TestUtils::array_equals (&random_data[samples / 2], sink->get_array(), samples / 2));
104 		CPPUNIT_ASSERT (TestUtils::array_equals (random_data, &sink->get_array()[samples / 2], samples));
105 		CPPUNIT_ASSERT (TestUtils::array_equals (random_data, &sink->get_array()[ 3 * samples / 2], samples / 2));
106 	}
107 
testChoppingProcess()108 	void testChoppingProcess()
109 	{
110 		sink.reset (new AppendingVectorSink<float>());
111 
112 		assert (samples % 2 == 0);
113 		chunker.reset (new Chunker<float>(samples / 4));
114 
115 		chunker->add_output (sink);
116 		samplecnt_t samples_output = 0;
117 
118 		ProcessContext<float> const half_context (random_data, samples / 2, 1);
119 		ProcessContext<float> const context (random_data, samples, 1);
120 
121 		// 0.5
122 		chunker->process (half_context);
123 		samples_output = sink->get_data().size();
124 		CPPUNIT_ASSERT_EQUAL ((samplecnt_t) samples / 2, samples_output);
125 
126 		// 1.5
127 		chunker->process (context);
128 		samples_output = sink->get_data().size();
129 		CPPUNIT_ASSERT_EQUAL ((samplecnt_t) samples / 2 * 3, samples_output);
130 
131 		// 2.5
132 		chunker->process (context);
133 		samples_output = sink->get_data().size();
134 		CPPUNIT_ASSERT_EQUAL (samples / 2 * 5, samples_output);
135 		CPPUNIT_ASSERT (TestUtils::array_equals (random_data, sink->get_array(), samples / 2));
136 		CPPUNIT_ASSERT (TestUtils::array_equals (random_data, &sink->get_array()[samples / 2], samples));
137 		CPPUNIT_ASSERT (TestUtils::array_equals (random_data, &sink->get_array()[ 3 * samples / 2], samples / 2));
138 	}
139 
testEndOfInputFlagHandling()140 	void testEndOfInputFlagHandling()
141 	{
142 		boost::shared_ptr<ProcessContextGrabber<float> > grabber(new ProcessContextGrabber<float>());
143 
144 		assert (samples % 2 == 0);
145 		chunker.reset (new Chunker<float>(samples));
146 		chunker->add_output (grabber);
147 
148 		ProcessContext<float> const half_context (random_data, samples / 2, 1);
149 		ProcessContext<float> const context (random_data, samples, 1);
150 		context.set_flag(ProcessContext<>::EndOfInput);
151 
152 		// Process 0.5 then 1.0
153 		chunker->process (half_context);
154 		chunker->process (context);
155 
156 		// Should output two contexts
157 		CPPUNIT_ASSERT_EQUAL((int)grabber->contexts.size(), 2);
158 		ProcessContextGrabber<float>::ContextList::iterator it = grabber->contexts.begin();
159 
160 		// first 1.0 not end of input
161 		CPPUNIT_ASSERT_EQUAL(it->samples(), samples);
162 		CPPUNIT_ASSERT(!it->has_flag(ProcessContext<>::EndOfInput));
163 
164 		// Then 0.5 with end of input
165 		++it;
166 		CPPUNIT_ASSERT_EQUAL(it->samples(), samples / 2);
167 		CPPUNIT_ASSERT(it->has_flag(ProcessContext<>::EndOfInput));
168 	}
169 
170   private:
171 	boost::shared_ptr<Chunker<float> > chunker;
172 	boost::shared_ptr<VectorSink<float> > sink;
173 
174 	float * random_data;
175 	samplecnt_t samples;
176 };
177 
178 CPPUNIT_TEST_SUITE_REGISTRATION (ChunkerTest);
179 
180