1 /* 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include <stdio.h> 12 #include <string.h> 13 14 #include <math.h> 15 16 #include "common_types.h" 17 #include "SpatialAudio.h" 18 #include "trace.h" 19 #include "utility.h" 20 #include "webrtc/test/testsupport/fileutils.h" 21 22 namespace webrtc { 23 24 #define NUM_PANN_COEFFS 10 25 26 SpatialAudio::SpatialAudio(int testMode) 27 : _acmLeft(AudioCodingModule::Create(1)), 28 _acmRight(AudioCodingModule::Create(2)), 29 _acmReceiver(AudioCodingModule::Create(3)), 30 _testMode(testMode) { 31 } 32 33 SpatialAudio::~SpatialAudio() { 34 delete _channel; 35 _inFile.Close(); 36 _outFile.Close(); 37 } 38 39 int16_t SpatialAudio::Setup() { 40 _channel = new Channel; 41 42 // Register callback for the sender side. 43 CHECK_ERROR(_acmLeft->RegisterTransportCallback(_channel)); 44 CHECK_ERROR(_acmRight->RegisterTransportCallback(_channel)); 45 // Register the receiver ACM in channel 46 _channel->RegisterReceiverACM(_acmReceiver.get()); 47 48 uint16_t sampFreqHz = 32000; 49 50 const std::string file_name = webrtc::test::ResourcePath( 51 "audio_coding/testfile32kHz", "pcm"); 52 _inFile.Open(file_name, sampFreqHz, "rb", false); 53 54 std::string output_file = webrtc::test::OutputPath() 55 + "out_spatial_autotest.pcm"; 56 if (_testMode == 1) { 57 output_file = webrtc::test::OutputPath() + "testspatial_out.pcm"; 58 printf("\n"); 59 printf("Enter the output file [%s]: ", output_file.c_str()); 60 PCMFile::ChooseFile(&output_file, MAX_FILE_NAME_LENGTH_BYTE, &sampFreqHz); 61 } else { 62 output_file = webrtc::test::OutputPath() + "testspatial_out.pcm"; 63 } 64 _outFile.Open(output_file, sampFreqHz, "wb", false); 65 _outFile.SaveStereo(true); 66 67 // Register all available codes as receiving codecs. 68 CodecInst codecInst; 69 int status; 70 uint8_t num_encoders = _acmReceiver->NumberOfCodecs(); 71 // Register all available codes as receiving codecs once more. 72 for (uint8_t n = 0; n < num_encoders; n++) { 73 status = _acmReceiver->Codec(n, &codecInst); 74 if (status < 0) { 75 printf("Error in Codec(), no matching codec found"); 76 } 77 status = _acmReceiver->RegisterReceiveCodec(codecInst); 78 if (status < 0) { 79 printf("Error in RegisterReceiveCodec() for payload type %d", 80 codecInst.pltype); 81 } 82 } 83 84 return 0; 85 } 86 87 void SpatialAudio::Perform() { 88 if (_testMode == 0) { 89 printf("Running SpatialAudio Test"); 90 WEBRTC_TRACE(webrtc::kTraceStateInfo, webrtc::kTraceAudioCoding, -1, 91 "---------- SpatialAudio ----------"); 92 } 93 94 Setup(); 95 96 CodecInst codecInst; 97 _acmLeft->Codec((uint8_t) 1, &codecInst); 98 CHECK_ERROR(_acmLeft->RegisterSendCodec(codecInst)); 99 EncodeDecode(); 100 101 int16_t pannCntr = 0; 102 103 double leftPanning[NUM_PANN_COEFFS] = { 1.00, 0.95, 0.90, 0.85, 0.80, 0.75, 104 0.70, 0.60, 0.55, 0.50 }; 105 double rightPanning[NUM_PANN_COEFFS] = { 0.50, 0.55, 0.60, 0.70, 0.75, 0.80, 106 0.85, 0.90, 0.95, 1.00 }; 107 108 while ((pannCntr + 1) < NUM_PANN_COEFFS) { 109 _acmLeft->Codec((uint8_t) 0, &codecInst); 110 codecInst.pacsize = 480; 111 CHECK_ERROR(_acmLeft->RegisterSendCodec(codecInst)); 112 CHECK_ERROR(_acmRight->RegisterSendCodec(codecInst)); 113 114 EncodeDecode(leftPanning[pannCntr], rightPanning[pannCntr]); 115 pannCntr++; 116 117 // Change codec 118 _acmLeft->Codec((uint8_t) 3, &codecInst); 119 codecInst.pacsize = 320; 120 CHECK_ERROR(_acmLeft->RegisterSendCodec(codecInst)); 121 CHECK_ERROR(_acmRight->RegisterSendCodec(codecInst)); 122 123 EncodeDecode(leftPanning[pannCntr], rightPanning[pannCntr]); 124 pannCntr++; 125 if (_testMode == 0) { 126 printf("."); 127 } 128 } 129 130 _acmLeft->Codec((uint8_t) 4, &codecInst); 131 CHECK_ERROR(_acmLeft->RegisterSendCodec(codecInst)); 132 EncodeDecode(); 133 134 _acmLeft->Codec((uint8_t) 0, &codecInst); 135 codecInst.pacsize = 480; 136 CHECK_ERROR(_acmLeft->RegisterSendCodec(codecInst)); 137 CHECK_ERROR(_acmRight->RegisterSendCodec(codecInst)); 138 pannCntr = NUM_PANN_COEFFS - 1; 139 while (pannCntr >= 0) { 140 EncodeDecode(leftPanning[pannCntr], rightPanning[pannCntr]); 141 pannCntr--; 142 if (_testMode == 0) { 143 printf("."); 144 } 145 } 146 if (_testMode == 0) { 147 printf("Done!\n"); 148 } 149 } 150 151 void SpatialAudio::EncodeDecode(const double leftPanning, 152 const double rightPanning) { 153 AudioFrame audioFrame; 154 int32_t outFileSampFreq = _outFile.SamplingFrequency(); 155 156 const double rightToLeftRatio = rightPanning / leftPanning; 157 158 _channel->SetIsStereo(true); 159 160 while (!_inFile.EndOfFile()) { 161 _inFile.Read10MsData(audioFrame); 162 for (int n = 0; n < audioFrame.samples_per_channel_; n++) { 163 audioFrame.data_[n] = (int16_t) floor( 164 audioFrame.data_[n] * leftPanning + 0.5); 165 } 166 CHECK_ERROR(_acmLeft->Add10MsData(audioFrame)); 167 168 for (int n = 0; n < audioFrame.samples_per_channel_; n++) { 169 audioFrame.data_[n] = (int16_t) floor( 170 audioFrame.data_[n] * rightToLeftRatio + 0.5); 171 } 172 CHECK_ERROR(_acmRight->Add10MsData(audioFrame)); 173 174 CHECK_ERROR(_acmLeft->Process()); 175 CHECK_ERROR(_acmRight->Process()); 176 177 CHECK_ERROR(_acmReceiver->PlayoutData10Ms(outFileSampFreq, &audioFrame)); 178 _outFile.Write10MsData(audioFrame); 179 } 180 _inFile.Rewind(); 181 } 182 183 void SpatialAudio::EncodeDecode() { 184 AudioFrame audioFrame; 185 int32_t outFileSampFreq = _outFile.SamplingFrequency(); 186 187 _channel->SetIsStereo(false); 188 189 while (!_inFile.EndOfFile()) { 190 _inFile.Read10MsData(audioFrame); 191 CHECK_ERROR(_acmLeft->Add10MsData(audioFrame)); 192 193 CHECK_ERROR(_acmLeft->Process()); 194 195 CHECK_ERROR(_acmReceiver->PlayoutData10Ms(outFileSampFreq, &audioFrame)); 196 _outFile.Write10MsData(audioFrame); 197 } 198 _inFile.Rewind(); 199 } 200 201 } // namespace webrtc 202