Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(218)

Side by Side Diff: ppapi/tests/test_media_stream_audio_track.cc

Issue 488533002: Add a test to verify the waveform from the Pepper MediaStream API is as (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@mediastream-samples-fix
Patch Set: Rebase. Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ppapi/tests/test_media_stream_audio_track.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 // 4 //
5 // Tests PPB_MediaStreamAudioTrack interface. 5 // Tests PPB_MediaStreamAudioTrack interface.
6 6
7 #include "ppapi/tests/test_media_stream_audio_track.h" 7 #include "ppapi/tests/test_media_stream_audio_track.h"
8 8
9 // For MSVC.
10 #define _USE_MATH_DEFINES
11 #include <math.h>
12 #include <stdint.h>
13
14 #include <algorithm>
15
9 #include "ppapi/c/private/ppb_testing_private.h" 16 #include "ppapi/c/private/ppb_testing_private.h"
10 #include "ppapi/cpp/audio_buffer.h" 17 #include "ppapi/cpp/audio_buffer.h"
11 #include "ppapi/cpp/completion_callback.h" 18 #include "ppapi/cpp/completion_callback.h"
12 #include "ppapi/cpp/instance.h" 19 #include "ppapi/cpp/instance.h"
13 #include "ppapi/cpp/var.h" 20 #include "ppapi/cpp/var.h"
14 #include "ppapi/tests/test_utils.h" 21 #include "ppapi/tests/test_utils.h"
15 #include "ppapi/tests/testing_instance.h" 22 #include "ppapi/tests/testing_instance.h"
16 23
17 REGISTER_TEST_CASE(MediaStreamAudioTrack); 24 REGISTER_TEST_CASE(MediaStreamAudioTrack);
18 25
(...skipping 14 matching lines...) Expand all
33 "}" 40 "}"
34 "var constraints = {" 41 "var constraints = {"
35 " audio: true," 42 " audio: true,"
36 " video: false," 43 " video: false,"
37 "};" 44 "};"
38 "navigator.getUserMedia = " 45 "navigator.getUserMedia = "
39 " navigator.getUserMedia || navigator.webkitGetUserMedia;" 46 " navigator.getUserMedia || navigator.webkitGetUserMedia;"
40 "navigator.getUserMedia(constraints," 47 "navigator.getUserMedia(constraints,"
41 " gotStream, function() {});"; 48 " gotStream, function() {});";
42 49
50 const char kSineJSCode[] =
51 // Create oscillators for the left and right channels. Use a sine wave,
52 // which is the easiest to calculate expected values. The oscillator output
53 // is low-pass filtered (as per spec) making comparison hard.
54 "var context = new AudioContext();"
55 "var l_osc = context.createOscillator();"
56 "l_osc.type = \"sine\";"
57 "l_osc.frequency.value = 25;"
58 "var r_osc = context.createOscillator();"
59 "r_osc.type = \"sine\";"
60 "r_osc.frequency.value = 100;"
61 // Combine the left and right channels.
62 "var merger = context.createChannelMerger(2);"
63 "merger.channelInterpretation = \"discrete\";"
64 "l_osc.connect(merger, 0, 0);"
65 "r_osc.connect(merger, 0, 1);"
66 "var dest_stream = context.createMediaStreamDestination();"
67 "merger.connect(dest_stream);"
68 // Dump the generated waveform to a MediaStream output.
69 "l_osc.start();"
70 "r_osc.start();"
71 "var track = dest_stream.stream.getAudioTracks()[0];"
72 "var plugin = document.getElementById('plugin');"
73 "plugin.postMessage(track);";
74
43 // Helper to check if the |sample_rate| is listed in PP_AudioBuffer_SampleRate 75 // Helper to check if the |sample_rate| is listed in PP_AudioBuffer_SampleRate
44 // enum. 76 // enum.
45 bool IsSampleRateValid(PP_AudioBuffer_SampleRate sample_rate) { 77 bool IsSampleRateValid(PP_AudioBuffer_SampleRate sample_rate) {
46 switch (sample_rate) { 78 switch (sample_rate) {
47 case PP_AUDIOBUFFER_SAMPLERATE_8000: 79 case PP_AUDIOBUFFER_SAMPLERATE_8000:
48 case PP_AUDIOBUFFER_SAMPLERATE_16000: 80 case PP_AUDIOBUFFER_SAMPLERATE_16000:
49 case PP_AUDIOBUFFER_SAMPLERATE_22050: 81 case PP_AUDIOBUFFER_SAMPLERATE_22050:
50 case PP_AUDIOBUFFER_SAMPLERATE_32000: 82 case PP_AUDIOBUFFER_SAMPLERATE_32000:
51 case PP_AUDIOBUFFER_SAMPLERATE_44100: 83 case PP_AUDIOBUFFER_SAMPLERATE_44100:
52 case PP_AUDIOBUFFER_SAMPLERATE_48000: 84 case PP_AUDIOBUFFER_SAMPLERATE_48000:
(...skipping 17 matching lines...) Expand all
70 } 102 }
71 103
72 TestMediaStreamAudioTrack::~TestMediaStreamAudioTrack() { 104 TestMediaStreamAudioTrack::~TestMediaStreamAudioTrack() {
73 } 105 }
74 106
75 void TestMediaStreamAudioTrack::RunTests(const std::string& filter) { 107 void TestMediaStreamAudioTrack::RunTests(const std::string& filter) {
76 RUN_TEST(Create, filter); 108 RUN_TEST(Create, filter);
77 RUN_TEST(GetBuffer, filter); 109 RUN_TEST(GetBuffer, filter);
78 RUN_TEST(Configure, filter); 110 RUN_TEST(Configure, filter);
79 RUN_TEST(ConfigureClose, filter); 111 RUN_TEST(ConfigureClose, filter);
112 RUN_TEST(VerifyWaveform, filter);
80 } 113 }
81 114
82 void TestMediaStreamAudioTrack::HandleMessage(const pp::Var& message) { 115 void TestMediaStreamAudioTrack::HandleMessage(const pp::Var& message) {
83 if (message.is_resource()) { 116 if (message.is_resource()) {
84 audio_track_ = pp::MediaStreamAudioTrack(message.AsResource()); 117 audio_track_ = pp::MediaStreamAudioTrack(message.AsResource());
85 } 118 }
86 event_.Signal(); 119 event_.Signal();
87 } 120 }
88 121
89 std::string TestMediaStreamAudioTrack::TestCreate() { 122 std::string TestMediaStreamAudioTrack::TestCreate() {
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
167 audio_track_.GetBuffer(cc_get_buffer.GetCallback())); 200 audio_track_.GetBuffer(cc_get_buffer.GetCallback()));
168 ASSERT_EQ(PP_OK, cc_get_buffer.result()); 201 ASSERT_EQ(PP_OK, cc_get_buffer.result());
169 pp::AudioBuffer buffer = cc_get_buffer.output(); 202 pp::AudioBuffer buffer = cc_get_buffer.output();
170 ASSERT_FALSE(buffer.is_null()); 203 ASSERT_FALSE(buffer.is_null());
171 ASSERT_TRUE(IsSampleRateValid(buffer.GetSampleRate())); 204 ASSERT_TRUE(IsSampleRateValid(buffer.GetSampleRate()));
172 ASSERT_EQ(buffer.GetSampleSize(), PP_AUDIOBUFFER_SAMPLESIZE_16_BITS); 205 ASSERT_EQ(buffer.GetSampleSize(), PP_AUDIOBUFFER_SAMPLESIZE_16_BITS);
173 206
174 ASSERT_GE(buffer.GetTimestamp(), timestamp); 207 ASSERT_GE(buffer.GetTimestamp(), timestamp);
175 timestamp = buffer.GetTimestamp(); 208 timestamp = buffer.GetTimestamp();
176 209
177 // TODO(amistry): Figure out how to inject a predictable audio pattern, such
178 // as a sawtooth, and check the buffer data to make sure it's correct.
179 ASSERT_TRUE(buffer.GetDataBuffer() != NULL); 210 ASSERT_TRUE(buffer.GetDataBuffer() != NULL);
180 if (expected_duration > 0) { 211 if (expected_duration > 0) {
181 uint32_t buffer_size = buffer.GetDataBufferSize(); 212 uint32_t buffer_size = buffer.GetDataBufferSize();
182 uint32_t channels = buffer.GetNumberOfChannels(); 213 uint32_t channels = buffer.GetNumberOfChannels();
183 uint32_t sample_rate = buffer.GetSampleRate(); 214 uint32_t sample_rate = buffer.GetSampleRate();
184 uint32_t bytes_per_frame = channels * 2; 215 uint32_t bytes_per_frame = channels * 2;
185 int32_t duration = expected_duration; 216 int32_t duration = expected_duration;
186 ASSERT_EQ(buffer_size % bytes_per_frame, 0U); 217 ASSERT_EQ(buffer_size % bytes_per_frame, 0U);
187 ASSERT_EQ(buffer_size, 218 ASSERT_EQ(buffer_size,
188 (duration * sample_rate * bytes_per_frame) / 1000); 219 (duration * sample_rate * bytes_per_frame) / 1000);
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
328 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result); 359 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
329 audio_track_.Close(); 360 audio_track_.Close();
330 cc_configure.WaitForResult(result); 361 cc_configure.WaitForResult(result);
331 result = cc_configure.result(); 362 result = cc_configure.result();
332 // Unfortunately, we can't control whether the configure succeeds or is 363 // Unfortunately, we can't control whether the configure succeeds or is
333 // aborted. 364 // aborted.
334 ASSERT_TRUE(result == PP_OK || result == PP_ERROR_ABORTED); 365 ASSERT_TRUE(result == PP_OK || result == PP_ERROR_ABORTED);
335 366
336 PASS(); 367 PASS();
337 } 368 }
369
370 uint32_t CalculateWaveStartingTime(int16_t sample, int16_t next_sample,
371 uint32_t period) {
372 int16_t slope = next_sample - sample;
373 double angle = asin(sample / (double)INT16_MAX);
374 if (slope < 0) {
375 angle = M_PI - angle;
376 }
377 if (angle < 0) {
378 angle += 2 * M_PI;
379 }
380 return round(angle * period / (2 * M_PI));
381 }
382
383 std::string TestMediaStreamAudioTrack::TestVerifyWaveform() {
384 // Create a track.
385 instance_->EvalScript(kSineJSCode);
386 event_.Wait();
387 event_.Reset();
388
389 ASSERT_FALSE(audio_track_.is_null());
390 ASSERT_FALSE(audio_track_.HasEnded());
391 ASSERT_FALSE(audio_track_.GetId().empty());
392
393 // Use a weird buffer length and number of buffers.
394 const int32_t kBufferSize = 13;
395 const int32_t kNumBuffers = 3;
396
397 const uint32_t kChannels = 2;
398 const uint32_t kFreqLeft = 25;
399 const uint32_t kFreqRight = 100;
400
401 int32_t attrib_list[] = {
402 PP_MEDIASTREAMAUDIOTRACK_ATTRIB_DURATION, kBufferSize,
403 PP_MEDIASTREAMAUDIOTRACK_ATTRIB_BUFFERS, kNumBuffers,
404 PP_MEDIASTREAMAUDIOTRACK_ATTRIB_NONE,
405 };
406 ASSERT_SUBTEST_SUCCESS(CheckConfigure(attrib_list, PP_OK));
407
408 // Get kNumBuffers buffers and verify they conform to the expected waveform.
409 PP_TimeDelta timestamp = 0.0;
410 int sample_time = 0;
411 uint32_t left_start = 0;
412 uint32_t right_start = 0;
413 for (int j = 0; j < kNumBuffers; ++j) {
414 TestCompletionCallbackWithOutput<pp::AudioBuffer> cc_get_buffer(
415 instance_->pp_instance(), false);
416 cc_get_buffer.WaitForResult(
417 audio_track_.GetBuffer(cc_get_buffer.GetCallback()));
418 ASSERT_EQ(PP_OK, cc_get_buffer.result());
419 pp::AudioBuffer buffer = cc_get_buffer.output();
420 ASSERT_FALSE(buffer.is_null());
421 ASSERT_TRUE(IsSampleRateValid(buffer.GetSampleRate()));
422 ASSERT_EQ(buffer.GetSampleSize(), PP_AUDIOBUFFER_SAMPLESIZE_16_BITS);
423 ASSERT_EQ(buffer.GetNumberOfChannels(), kChannels);
424 ASSERT_GE(buffer.GetTimestamp(), timestamp);
425 timestamp = buffer.GetTimestamp();
426
427 uint32_t buffer_size = buffer.GetDataBufferSize();
428 uint32_t sample_rate = buffer.GetSampleRate();
429 uint32_t num_samples = buffer.GetNumberOfSamples();
430 uint32_t bytes_per_frame = kChannels * 2;
431 ASSERT_EQ(num_samples, (kChannels * kBufferSize * sample_rate) / 1000);
432 ASSERT_EQ(buffer_size % bytes_per_frame, 0U);
433 ASSERT_EQ(buffer_size, num_samples * 2);
434
435 // Period of sine wave, in samples.
436 uint32_t left_period = sample_rate / kFreqLeft;
437 uint32_t right_period = sample_rate / kFreqRight;
438
439 int16_t* data_buffer = static_cast<int16_t*>(buffer.GetDataBuffer());
440 ASSERT_TRUE(data_buffer != NULL);
441
442 if (j == 0) {
443 // The generated wave doesn't necessarily start at 0, so compensate for
444 // this.
445 left_start = CalculateWaveStartingTime(data_buffer[0], data_buffer[2],
446 left_period);
447 right_start = CalculateWaveStartingTime(data_buffer[1], data_buffer[3],
448 right_period);
449 }
450
451 for (uint32_t sample = 0; sample < num_samples;
452 sample += 2, sample_time++) {
453 int16_t left = data_buffer[sample];
454 int16_t right = data_buffer[sample + 1];
455 double angle = (2.0 * M_PI * ((sample_time + left_start) % left_period)) /
456 left_period;
457 int16_t expected = INT16_MAX * sin(angle);
458 // Account for off-by-one errors due to rounding.
459 ASSERT_GE(left, std::max<int16_t>(expected, INT16_MIN + 1) - 1);
460 ASSERT_LE(left, std::min<int16_t>(expected, INT16_MAX - 1) + 1);
461
462 angle = (2 * M_PI * ((sample_time + right_start) % right_period)) /
463 right_period;
464 expected = INT16_MAX * sin(angle);
465 ASSERT_GE(right, std::max<int16_t>(expected, INT16_MIN + 1) - 1);
466 ASSERT_LE(right, std::min<int16_t>(expected, INT16_MAX - 1) + 1);
467 }
468
469 audio_track_.RecycleBuffer(buffer);
470 }
471
472 PASS();
473 }
OLDNEW
« no previous file with comments | « ppapi/tests/test_media_stream_audio_track.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698