| /* |
| * Copyright (c) 2011 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 "common_types.h" |
| #include "SpatialAudio.h" |
| #include "trace.h" |
| #include "testsupport/fileutils.h" |
| #include "utility.h" |
| |
| namespace webrtc { |
| |
| #define NUM_PANN_COEFFS 10 |
| |
| SpatialAudio::SpatialAudio(int testMode) |
| { |
| _testMode = testMode; |
| } |
| |
| SpatialAudio::~SpatialAudio() |
| { |
| AudioCodingModule::Destroy(_acmLeft); |
| AudioCodingModule::Destroy(_acmRight); |
| AudioCodingModule::Destroy(_acmReceiver); |
| delete _channel; |
| _inFile.Close(); |
| _outFile.Close(); |
| } |
| |
| WebRtc_Word16 |
| SpatialAudio::Setup() |
| { |
| // Create ACMs and the Channel; |
| _acmLeft = AudioCodingModule::Create(1); |
| _acmRight = AudioCodingModule::Create(2); |
| _acmReceiver = AudioCodingModule::Create(3); |
| _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); |
| |
| WebRtc_Word8 audioFileName[MAX_FILE_NAME_LENGTH_BYTE]; |
| WebRtc_UWord16 sampFreqHz = 32000; |
| |
| strncpy(audioFileName, "./test/data/audio_coding/testfile32kHz.pcm", |
| MAX_FILE_NAME_LENGTH_BYTE - 1); |
| if(_testMode == 1) |
| { |
| printf("Enter the input file [%s]: ", audioFileName); |
| PCMFile::ChooseFile(audioFileName, MAX_FILE_NAME_LENGTH_BYTE, &sampFreqHz); |
| } |
| _inFile.Open(audioFileName, sampFreqHz, "rb", false); |
| |
| if(_testMode == 0) |
| { |
| std::string outputFile = webrtc::test::OutputPath() + |
| "out_spatial_autotest.pcm"; |
| strncpy(audioFileName, outputFile.c_str(), |
| MAX_FILE_NAME_LENGTH_BYTE - 1); |
| } |
| else if(_testMode == 1) |
| { |
| printf("\n"); |
| std::string outputFile = webrtc::test::OutputPath() + |
| "testspatial_out.pcm"; |
| strncpy(audioFileName, outputFile.c_str(), |
| MAX_FILE_NAME_LENGTH_BYTE - 1); |
| printf("Enter the output file [%s]: ", audioFileName); |
| PCMFile::ChooseFile(audioFileName, MAX_FILE_NAME_LENGTH_BYTE, &sampFreqHz); |
| } |
| else |
| { |
| std::string outputFile = webrtc::test::OutputPath() + |
| "testspatial_out.pcm"; |
| strncpy(audioFileName, outputFile.c_str(), |
| MAX_FILE_NAME_LENGTH_BYTE - 1); |
| } |
| _outFile.Open(audioFileName, sampFreqHz, "wb", false); |
| _outFile.SaveStereo(true); |
| |
| |
| // Register couple of codecs as receive codec |
| CodecInst codecInst; |
| |
| _acmLeft->Codec((WebRtc_UWord8)0, codecInst); |
| codecInst.channels = 2; |
| CHECK_ERROR(_acmReceiver->RegisterReceiveCodec(codecInst)); |
| |
| _acmLeft->Codec((WebRtc_UWord8)3, codecInst); |
| codecInst.channels = 2; |
| CHECK_ERROR(_acmReceiver->RegisterReceiveCodec(codecInst)); |
| |
| _acmLeft->Codec((WebRtc_UWord8)1, codecInst); |
| CHECK_ERROR(_acmReceiver->RegisterReceiveCodec(codecInst)); |
| |
| _acmLeft->Codec((WebRtc_UWord8)4, codecInst); |
| CHECK_ERROR(_acmReceiver->RegisterReceiveCodec(codecInst)); |
| |
| 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((WebRtc_UWord8)1, codecInst); |
| CHECK_ERROR(_acmLeft->RegisterSendCodec(codecInst)); |
| EncodeDecode(); |
| |
| WebRtc_Word16 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((WebRtc_UWord8)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((WebRtc_UWord8)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((WebRtc_UWord8)4, codecInst); |
| CHECK_ERROR(_acmLeft->RegisterSendCodec(codecInst)); |
| EncodeDecode(); |
| |
| _acmLeft->Codec((WebRtc_UWord8)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; |
| WebRtc_Word32 outFileSampFreq = _outFile.SamplingFrequency(); |
| |
| const double rightToLeftRatio = rightPanning / leftPanning; |
| |
| _channel->SetIsStereo(true); |
| |
| while(!_inFile.EndOfFile()) |
| { |
| _inFile.Read10MsData(audioFrame); |
| for(int n = 0; n < audioFrame._payloadDataLengthInSamples; n++) |
| { |
| audioFrame._payloadData[n] = (WebRtc_Word16)floor( |
| audioFrame._payloadData[n] * leftPanning + 0.5); |
| } |
| CHECK_ERROR(_acmLeft->Add10MsData(audioFrame)); |
| |
| for(int n = 0; n < audioFrame._payloadDataLengthInSamples; n++) |
| { |
| audioFrame._payloadData[n] = (WebRtc_Word16)floor( |
| audioFrame._payloadData[n] * rightToLeftRatio + 0.5); |
| } |
| CHECK_ERROR(_acmRight->Add10MsData(audioFrame)); |
| |
| CHECK_ERROR(_acmLeft->Process()); |
| CHECK_ERROR(_acmRight->Process()); |
| |
| CHECK_ERROR(_acmReceiver->PlayoutData10Ms(outFileSampFreq, audioFrame)); |
| _outFile.Write10MsData(audioFrame); |
| } |
| _inFile.Rewind(); |
| } |
| |
| void |
| SpatialAudio::EncodeDecode() |
| { |
| AudioFrame audioFrame; |
| WebRtc_Word32 outFileSampFreq = _outFile.SamplingFrequency(); |
| |
| _channel->SetIsStereo(false); |
| |
| while(!_inFile.EndOfFile()) |
| { |
| _inFile.Read10MsData(audioFrame); |
| CHECK_ERROR(_acmLeft->Add10MsData(audioFrame)); |
| |
| CHECK_ERROR(_acmLeft->Process()); |
| |
| CHECK_ERROR(_acmReceiver->PlayoutData10Ms(outFileSampFreq, audioFrame)); |
| _outFile.Write10MsData(audioFrame); |
| } |
| _inFile.Rewind(); |
| } |
| |
| } // namespace webrtc |