| /* | |
| * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | |
| * | |
| * Use of this source code is governed by a BSD-style license | |
| * that can be found in the LICENSE file in the root of the source | |
| * tree. An additional intellectual property rights grant can be found | |
| * in the file PATENTS. All contributing project authors may | |
| * be found in the AUTHORS file in the root of the source tree. | |
| */ | |
| #include <stdio.h> | |
| #include <string.h> | |
| #include <math.h> | |
| #include "webrtc/common_types.h" | |
| #include "webrtc/modules/audio_coding/main/test/SpatialAudio.h" | |
| #include "webrtc/system_wrappers/interface/trace.h" | |
| #include "webrtc/system_wrappers/interface/trace.h" | |
| #include "webrtc/test/testsupport/fileutils.h" | |
| namespace webrtc { | |
| #define NUM_PANN_COEFFS 10 | |
| SpatialAudio::SpatialAudio(int testMode) | |
| : _acmLeft(AudioCodingModule::Create(1)), | |
| _acmRight(AudioCodingModule::Create(2)), | |
| _acmReceiver(AudioCodingModule::Create(3)), | |
| _testMode(testMode) { | |
| } | |
| SpatialAudio::~SpatialAudio() { | |
| delete _channel; | |
| _inFile.Close(); | |
| _outFile.Close(); | |
| } | |
| int16_t SpatialAudio::Setup() { | |
| _channel = new Channel; | |
| // Register callback for the sender side. | |
| CHECK_ERROR(_acmLeft->RegisterTransportCallback(_channel)); | |
| CHECK_ERROR(_acmRight->RegisterTransportCallback(_channel)); | |
| // Register the receiver ACM in channel | |
| _channel->RegisterReceiverACM(_acmReceiver.get()); | |
| uint16_t sampFreqHz = 32000; | |
| const std::string file_name = webrtc::test::ResourcePath( | |
| "audio_coding/testfile32kHz", "pcm"); | |
| _inFile.Open(file_name, sampFreqHz, "rb", false); | |
| std::string output_file = webrtc::test::OutputPath() | |
| + "out_spatial_autotest.pcm"; | |
| if (_testMode == 1) { | |
| output_file = webrtc::test::OutputPath() + "testspatial_out.pcm"; | |
| printf("\n"); | |
| printf("Enter the output file [%s]: ", output_file.c_str()); | |
| PCMFile::ChooseFile(&output_file, MAX_FILE_NAME_LENGTH_BYTE, &sampFreqHz); | |
| } else { | |
| output_file = webrtc::test::OutputPath() + "testspatial_out.pcm"; | |
| } | |
| _outFile.Open(output_file, sampFreqHz, "wb", false); | |
| _outFile.SaveStereo(true); | |
| // Register all available codes as receiving codecs. | |
| CodecInst codecInst; | |
| int status; | |
| uint8_t num_encoders = _acmReceiver->NumberOfCodecs(); | |
| // Register all available codes as receiving codecs once more. | |
| for (uint8_t n = 0; n < num_encoders; n++) { | |
| status = _acmReceiver->Codec(n, &codecInst); | |
| if (status < 0) { | |
| printf("Error in Codec(), no matching codec found"); | |
| } | |
| status = _acmReceiver->RegisterReceiveCodec(codecInst); | |
| if (status < 0) { | |
| printf("Error in RegisterReceiveCodec() for payload type %d", | |
| codecInst.pltype); | |
| } | |
| } | |
| return 0; | |
| } | |
| void SpatialAudio::Perform() { | |
| if (_testMode == 0) { | |
| printf("Running SpatialAudio Test"); | |
| WEBRTC_TRACE(webrtc::kTraceStateInfo, webrtc::kTraceAudioCoding, -1, | |
| "---------- SpatialAudio ----------"); | |
| } | |
| Setup(); | |
| CodecInst codecInst; | |
| _acmLeft->Codec((uint8_t) 1, &codecInst); | |
| CHECK_ERROR(_acmLeft->RegisterSendCodec(codecInst)); | |
| EncodeDecode(); | |
| int16_t pannCntr = 0; | |
| double leftPanning[NUM_PANN_COEFFS] = { 1.00, 0.95, 0.90, 0.85, 0.80, 0.75, | |
| 0.70, 0.60, 0.55, 0.50 }; | |
| double rightPanning[NUM_PANN_COEFFS] = { 0.50, 0.55, 0.60, 0.70, 0.75, 0.80, | |
| 0.85, 0.90, 0.95, 1.00 }; | |
| while ((pannCntr + 1) < NUM_PANN_COEFFS) { | |
| _acmLeft->Codec((uint8_t) 0, &codecInst); | |
| codecInst.pacsize = 480; | |
| CHECK_ERROR(_acmLeft->RegisterSendCodec(codecInst)); | |
| CHECK_ERROR(_acmRight->RegisterSendCodec(codecInst)); | |
| EncodeDecode(leftPanning[pannCntr], rightPanning[pannCntr]); | |
| pannCntr++; | |
| // Change codec | |
| _acmLeft->Codec((uint8_t) 3, &codecInst); | |
| codecInst.pacsize = 320; | |
| CHECK_ERROR(_acmLeft->RegisterSendCodec(codecInst)); | |
| CHECK_ERROR(_acmRight->RegisterSendCodec(codecInst)); | |
| EncodeDecode(leftPanning[pannCntr], rightPanning[pannCntr]); | |
| pannCntr++; | |
| if (_testMode == 0) { | |
| printf("."); | |
| } | |
| } | |
| _acmLeft->Codec((uint8_t) 4, &codecInst); | |
| CHECK_ERROR(_acmLeft->RegisterSendCodec(codecInst)); | |
| EncodeDecode(); | |
| _acmLeft->Codec((uint8_t) 0, &codecInst); | |
| codecInst.pacsize = 480; | |
| CHECK_ERROR(_acmLeft->RegisterSendCodec(codecInst)); | |
| CHECK_ERROR(_acmRight->RegisterSendCodec(codecInst)); | |
| pannCntr = NUM_PANN_COEFFS - 1; | |
| while (pannCntr >= 0) { | |
| EncodeDecode(leftPanning[pannCntr], rightPanning[pannCntr]); | |
| pannCntr--; | |
| if (_testMode == 0) { | |
| printf("."); | |
| } | |
| } | |
| if (_testMode == 0) { | |
| printf("Done!\n"); | |
| } | |
| } | |
| void SpatialAudio::EncodeDecode(const double leftPanning, | |
| const double rightPanning) { | |
| AudioFrame audioFrame; | |
| int32_t outFileSampFreq = _outFile.SamplingFrequency(); | |
| const double rightToLeftRatio = rightPanning / leftPanning; | |
| _channel->SetIsStereo(true); | |
| while (!_inFile.EndOfFile()) { | |
| _inFile.Read10MsData(audioFrame); | |
| for (int n = 0; n < audioFrame.samples_per_channel_; n++) { | |
| audioFrame.data_[n] = (int16_t) floor( | |
| audioFrame.data_[n] * leftPanning + 0.5); | |
| } | |
| CHECK_ERROR(_acmLeft->Add10MsData(audioFrame)); | |
| for (int n = 0; n < audioFrame.samples_per_channel_; n++) { | |
| audioFrame.data_[n] = (int16_t) floor( | |
| audioFrame.data_[n] * rightToLeftRatio + 0.5); | |
| } | |
| CHECK_ERROR(_acmRight->Add10MsData(audioFrame)); | |
| CHECK_ERROR(_acmReceiver->PlayoutData10Ms(outFileSampFreq, &audioFrame)); | |
| _outFile.Write10MsData(audioFrame); | |
| } | |
| _inFile.Rewind(); | |
| } | |
| void SpatialAudio::EncodeDecode() { | |
| AudioFrame audioFrame; | |
| int32_t outFileSampFreq = _outFile.SamplingFrequency(); | |
| _channel->SetIsStereo(false); | |
| while (!_inFile.EndOfFile()) { | |
| _inFile.Read10MsData(audioFrame); | |
| CHECK_ERROR(_acmLeft->Add10MsData(audioFrame)); | |
| CHECK_ERROR(_acmReceiver->PlayoutData10Ms(outFileSampFreq, &audioFrame)); | |
| _outFile.Write10MsData(audioFrame); | |
| } | |
| _inFile.Rewind(); | |
| } | |
| } // namespace webrtc |