/* * 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 #include #include #include "SpatialAudio.h" #include "utility.h" #include "trace.h" #include "common_types.h" using 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, "./modules/audio_coding/main/test/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) { strncpy(audioFileName, "./modules/audio_coding/main/test/res_autotests/out_spatial_autotest.pcm", MAX_FILE_NAME_LENGTH_BYTE - 1); } else if(_testMode == 1) { printf("\n"); strncpy(audioFileName, "./modules/audio_coding/main/test/res_tests/testspatial_out.pcm", MAX_FILE_NAME_LENGTH_BYTE - 1); printf("Enter the output file [%s]: ", audioFileName); PCMFile::ChooseFile(audioFileName, MAX_FILE_NAME_LENGTH_BYTE, &sampFreqHz); } else { strncpy(audioFileName, "./modules/audio_coding/main/test/res_tests/testspatial_out.pcm", 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(); }