| /* |
| * 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. |
| */ |
| |
| // SwitchingSampRate.cpp : Defines the entry point for the console |
| // application. |
| // |
| |
| #include <iostream> |
| #include "isac.h" |
| #include "utility.h" |
| #include "signal_processing_library.h" |
| |
| #define MAX_FILE_NAME 500 |
| #define MAX_NUM_CLIENTS 2 |
| |
| |
| #define NUM_CLIENTS 2 |
| |
| using namespace std; |
| |
| int main(int argc, char* argv[]) |
| { |
| char fileNameWB[MAX_FILE_NAME]; |
| char fileNameSWB[MAX_FILE_NAME]; |
| |
| char outFileName[MAX_NUM_CLIENTS][MAX_FILE_NAME]; |
| |
| FILE* inFile[MAX_NUM_CLIENTS]; |
| FILE* outFile[MAX_NUM_CLIENTS]; |
| |
| ISACStruct* codecInstance[MAX_NUM_CLIENTS]; |
| int32_t resamplerState[MAX_NUM_CLIENTS][8]; |
| |
| int encoderSampRate[MAX_NUM_CLIENTS]; |
| |
| int minBn = 16000; |
| int maxBn = 56000; |
| |
| int bnWB = 32000; |
| int bnSWB = 56000; |
| |
| strcpy(outFileName[0], "switchSampRate_out1.pcm"); |
| strcpy(outFileName[1], "switchSampRate_out2.pcm"); |
| |
| short clientCntr; |
| |
| size_t lenEncodedInBytes[MAX_NUM_CLIENTS]; |
| unsigned int lenAudioIn10ms[MAX_NUM_CLIENTS]; |
| size_t lenEncodedInBytesTmp[MAX_NUM_CLIENTS]; |
| unsigned int lenAudioIn10msTmp[MAX_NUM_CLIENTS]; |
| BottleNeckModel* packetData[MAX_NUM_CLIENTS]; |
| |
| char versionNumber[100]; |
| short samplesIn10ms[MAX_NUM_CLIENTS]; |
| int bottleneck[MAX_NUM_CLIENTS]; |
| |
| printf("\n\n"); |
| printf("____________________________________________\n\n"); |
| WebRtcIsac_version(versionNumber); |
| printf(" iSAC-swb version %s\n", versionNumber); |
| printf("____________________________________________\n"); |
| |
| |
| fileNameWB[0] = '\0'; |
| fileNameSWB[0] = '\0'; |
| |
| char myFlag[20]; |
| strcpy(myFlag, "-wb"); |
| // READ THE WIDEBAND AND SUPER-WIDEBAND FILE NAMES |
| if(readParamString(argc, argv, myFlag, fileNameWB, MAX_FILE_NAME) <= 0) |
| { |
| printf("No wideband file is specified"); |
| } |
| |
| strcpy(myFlag, "-swb"); |
| if(readParamString(argc, argv, myFlag, fileNameSWB, MAX_FILE_NAME) <= 0) |
| { |
| printf("No super-wideband file is specified"); |
| } |
| |
| // THE FIRST CLIENT STARTS IN WIDEBAND |
| encoderSampRate[0] = 16000; |
| OPEN_FILE_RB(inFile[0], fileNameWB); |
| |
| // THE SECOND CLIENT STARTS IN SUPER-WIDEBAND |
| encoderSampRate[1] = 32000; |
| OPEN_FILE_RB(inFile[1], fileNameSWB); |
| |
| strcpy(myFlag, "-I"); |
| short codingMode = readSwitch(argc, argv, myFlag); |
| |
| for(clientCntr = 0; clientCntr < NUM_CLIENTS; clientCntr++) |
| { |
| codecInstance[clientCntr] = NULL; |
| |
| printf("\n"); |
| printf("Client %d\n", clientCntr + 1); |
| printf("---------\n"); |
| printf("Starting %s", |
| (encoderSampRate[clientCntr] == 16000) |
| ? "wideband":"super-wideband"); |
| |
| // Open output File Name |
| OPEN_FILE_WB(outFile[clientCntr], outFileName[clientCntr]); |
| printf("Output File...................... %s\n", outFileName[clientCntr]); |
| |
| samplesIn10ms[clientCntr] = encoderSampRate[clientCntr] * 10; |
| |
| if(codingMode == 1) |
| { |
| bottleneck[clientCntr] = (clientCntr)? bnSWB:bnWB; |
| } |
| else |
| { |
| bottleneck[clientCntr] = (clientCntr)? minBn:maxBn; |
| } |
| |
| printf("Bottleneck....................... %0.3f kbits/sec \n", |
| bottleneck[clientCntr] / 1000.0); |
| |
| // coding-mode |
| printf("Encoding Mode.................... %s\n", |
| (codingMode == 1)? "Channel-Independent (Instantaneous)":"Adaptive"); |
| |
| lenEncodedInBytes[clientCntr] = 0; |
| lenAudioIn10ms[clientCntr] = 0; |
| lenEncodedInBytesTmp[clientCntr] = 0; |
| lenAudioIn10msTmp[clientCntr] = 0; |
| |
| packetData[clientCntr] = (BottleNeckModel*)new(BottleNeckModel); |
| if(packetData[clientCntr] == NULL) |
| { |
| printf("Could not allocate memory for packetData \n"); |
| return -1; |
| } |
| memset(packetData[clientCntr], 0, sizeof(BottleNeckModel)); |
| memset(resamplerState[clientCntr], 0, sizeof(int32_t) * 8); |
| } |
| |
| for(clientCntr = 0; clientCntr < NUM_CLIENTS; clientCntr++) |
| { |
| // Create |
| if(WebRtcIsac_Create(&codecInstance[clientCntr])) |
| { |
| printf("Could not creat client %d\n", clientCntr + 1); |
| return -1; |
| } |
| |
| WebRtcIsac_SetEncSampRate(codecInstance[clientCntr], encoderSampRate[clientCntr]); |
| |
| WebRtcIsac_SetDecSampRate(codecInstance[clientCntr], |
| encoderSampRate[clientCntr + (1 - ((clientCntr & 1)<<1))]); |
| |
| // Initialize Encoder |
| if(WebRtcIsac_EncoderInit(codecInstance[clientCntr], |
| codingMode) < 0) |
| { |
| printf("Could not initialize client, %d\n", clientCntr + 1); |
| return -1; |
| } |
| |
| WebRtcIsac_DecoderInit(codecInstance[clientCntr]); |
| |
| // setup Rate if in Instantaneous mode |
| if(codingMode != 0) |
| { |
| // ONLY Clients who are not in Adaptive mode |
| if(WebRtcIsac_Control(codecInstance[clientCntr], |
| bottleneck[clientCntr], 30) < 0) |
| { |
| printf("Could not setup bottleneck and frame-size for client %d\n", |
| clientCntr + 1); |
| return -1; |
| } |
| } |
| } |
| |
| |
| size_t streamLen; |
| short numSamplesRead; |
| size_t lenDecodedAudio; |
| short senderIdx; |
| short receiverIdx; |
| |
| printf("\n"); |
| short num10ms[MAX_NUM_CLIENTS]; |
| memset(num10ms, 0, sizeof(short)*MAX_NUM_CLIENTS); |
| FILE* arrivalTimeFile1 = fopen("arrivalTime1.dat", "wb"); |
| FILE* arrivalTimeFile2 = fopen("arrivalTime2.dat", "wb"); |
| short numPrint[MAX_NUM_CLIENTS]; |
| memset(numPrint, 0, sizeof(short) * MAX_NUM_CLIENTS); |
| |
| // Audio Buffers |
| short silence10ms[10 * 32]; |
| memset(silence10ms, 0, 320 * sizeof(short)); |
| short audioBuff10ms[10 * 32]; |
| short audioBuff60ms[60 * 32]; |
| short resampledAudio60ms[60 * 32]; |
| |
| unsigned short bitStream[600+600]; |
| short speechType[1]; |
| |
| short numSampFreqChanged = 0; |
| while(numSampFreqChanged < 10) |
| { |
| for(clientCntr = 0; clientCntr < NUM_CLIENTS; clientCntr++) |
| { |
| // Encoding/decoding for this pair of clients, if there is |
| // audio for any of them |
| //if(audioLeft[clientCntr] || audioLeft[clientCntr + 1]) |
| //{ |
| //for(pairCntr = 0; pairCntr < 2; pairCntr++) |
| //{ |
| senderIdx = clientCntr; // + pairCntr; |
| receiverIdx = 1 - clientCntr;// + (1 - pairCntr); |
| |
| //if(num10ms[senderIdx] > 6) |
| //{ |
| // printf("Too many frames read for client %d", |
| // senderIdx + 1); |
| // return -1; |
| //} |
| |
| numSamplesRead = (short)fread(audioBuff10ms, sizeof(short), |
| samplesIn10ms[senderIdx], inFile[senderIdx]); |
| if(numSamplesRead != samplesIn10ms[senderIdx]) |
| { |
| // file finished switch encoder sampling frequency. |
| printf("Changing Encoder Sampling frequency in client %d to ", senderIdx+1); |
| fclose(inFile[senderIdx]); |
| numSampFreqChanged++; |
| if(encoderSampRate[senderIdx] == 16000) |
| { |
| printf("super-wideband.\n"); |
| OPEN_FILE_RB(inFile[senderIdx], fileNameSWB); |
| encoderSampRate[senderIdx] = 32000; |
| } |
| else |
| { |
| printf("wideband.\n"); |
| OPEN_FILE_RB(inFile[senderIdx], fileNameWB); |
| encoderSampRate[senderIdx] = 16000; |
| } |
| WebRtcIsac_SetEncSampRate(codecInstance[senderIdx], encoderSampRate[senderIdx]); |
| WebRtcIsac_SetDecSampRate(codecInstance[receiverIdx], encoderSampRate[senderIdx]); |
| |
| samplesIn10ms[clientCntr] = encoderSampRate[clientCntr] * 10; |
| |
| numSamplesRead = (short)fread(audioBuff10ms, sizeof(short), |
| samplesIn10ms[senderIdx], inFile[senderIdx]); |
| if(numSamplesRead != samplesIn10ms[senderIdx]) |
| { |
| printf(" File %s for client %d has not enough audio\n", |
| (encoderSampRate[senderIdx]==16000)? "wideband":"super-wideband", |
| senderIdx + 1); |
| return -1; |
| } |
| } |
| num10ms[senderIdx]++; |
| |
| // sanity check |
| //if(num10ms[senderIdx] > 6) |
| //{ |
| // printf("Client %d has got more than 60 ms audio and encoded no packet.\n", |
| // senderIdx); |
| // return -1; |
| //} |
| |
| // Encode |
| |
| |
| int streamLen_int = WebRtcIsac_Encode(codecInstance[senderIdx], |
| audioBuff10ms, |
| (uint8_t*)bitStream); |
| int16_t ggg; |
| if (streamLen_int > 0) { |
| if ((WebRtcIsac_ReadFrameLen( |
| codecInstance[receiverIdx], |
| reinterpret_cast<const uint8_t*>(bitStream), |
| &ggg)) < 0) |
| printf("ERROR\n"); |
| } |
| |
| // Sanity check |
| if(streamLen_int < 0) |
| { |
| printf(" Encoder error in client %d \n", senderIdx + 1); |
| return -1; |
| } |
| streamLen = static_cast<size_t>(streamLen_int); |
| |
| |
| if(streamLen > 0) |
| { |
| // Packet generated; model sending through a channel, do bandwidth |
| // estimation at the receiver and decode. |
| lenEncodedInBytes[senderIdx] += streamLen; |
| lenAudioIn10ms[senderIdx] += (unsigned int)num10ms[senderIdx]; |
| lenEncodedInBytesTmp[senderIdx] += streamLen; |
| lenAudioIn10msTmp[senderIdx] += (unsigned int)num10ms[senderIdx]; |
| |
| // Print after ~5 sec. |
| if(lenAudioIn10msTmp[senderIdx] >= 100) |
| { |
| numPrint[senderIdx]++; |
| printf(" %d, %6.3f => %6.3f ", senderIdx+1, |
| bottleneck[senderIdx] / 1000.0, |
| lenEncodedInBytesTmp[senderIdx] * 0.8 / |
| lenAudioIn10msTmp[senderIdx]); |
| |
| if(codingMode == 0) |
| { |
| int32_t bn; |
| WebRtcIsac_GetUplinkBw(codecInstance[senderIdx], &bn); |
| printf("[%d] ", bn); |
| } |
| //int16_t rateIndexLB; |
| //int16_t rateIndexUB; |
| //WebRtcIsac_GetDownLinkBwIndex(codecInstance[receiverIdx], |
| // &rateIndexLB, &rateIndexUB); |
| //printf(" (%2d, %2d) ", rateIndexLB, rateIndexUB); |
| |
| cout << flush; |
| lenEncodedInBytesTmp[senderIdx] = 0; |
| lenAudioIn10msTmp[senderIdx] = 0; |
| //if(senderIdx == (NUM_CLIENTS - 1)) |
| //{ |
| printf(" %0.1f \n", lenAudioIn10ms[senderIdx] * 10. /1000); |
| //} |
| |
| // After ~20 sec change the bottleneck. |
| // if((numPrint[senderIdx] == 4) && (codingMode == 0)) |
| // { |
| // numPrint[senderIdx] = 0; |
| // if(codingMode == 0) |
| // { |
| // int newBottleneck = bottleneck[senderIdx] + |
| // (bottleneckChange[senderIdx] * 1000); |
| |
| // if(bottleneckChange[senderIdx] > 0) |
| // { |
| // if(newBottleneck >maxBn) |
| // { |
| // bottleneckChange[senderIdx] = -1; |
| // newBottleneck = bottleneck[senderIdx] + |
| // (bottleneckChange[senderIdx] * 1000); |
| // if(newBottleneck > minBn) |
| // { |
| // bottleneck[senderIdx] = newBottleneck; |
| // } |
| // } |
| // else |
| // { |
| // bottleneck[senderIdx] = newBottleneck; |
| // } |
| // } |
| // else |
| // { |
| // if(newBottleneck < minBn) |
| // { |
| // bottleneckChange[senderIdx] = 1; |
| // newBottleneck = bottleneck[senderIdx] + |
| // (bottleneckChange[senderIdx] * 1000); |
| // if(newBottleneck < maxBn) |
| // { |
| // bottleneck[senderIdx] = newBottleneck; |
| // } |
| // } |
| // else |
| // { |
| // bottleneck[senderIdx] = newBottleneck; |
| // } |
| // } |
| // } |
| // } |
| } |
| |
| // model a channel of given bottleneck, to get the receive timestamp |
| get_arrival_time(num10ms[senderIdx] * samplesIn10ms[senderIdx], |
| streamLen, bottleneck[senderIdx], packetData[senderIdx], |
| encoderSampRate[senderIdx]*1000, encoderSampRate[senderIdx]*1000); |
| |
| // Write the arrival time. |
| if(senderIdx == 0) |
| { |
| if (fwrite(&(packetData[senderIdx]->arrival_time), |
| sizeof(unsigned int), |
| 1, arrivalTimeFile1) != 1) { |
| return -1; |
| } |
| } |
| else |
| { |
| if (fwrite(&(packetData[senderIdx]->arrival_time), |
| sizeof(unsigned int), |
| 1, arrivalTimeFile2) != 1) { |
| return -1; |
| } |
| } |
| |
| // BWE |
| if (WebRtcIsac_UpdateBwEstimate( |
| codecInstance[receiverIdx], |
| reinterpret_cast<const uint8_t*>(bitStream), |
| streamLen, |
| packetData[senderIdx]->rtp_number, |
| packetData[senderIdx]->sample_count, |
| packetData[senderIdx]->arrival_time) < 0) { |
| printf(" BWE Error at client %d \n", receiverIdx + 1); |
| return -1; |
| } |
| /**/ |
| // Decode |
| int lenDecodedAudio_int = WebRtcIsac_Decode( |
| codecInstance[receiverIdx], |
| reinterpret_cast<const uint8_t*>(bitStream), |
| streamLen, |
| audioBuff60ms, |
| speechType); |
| if(lenDecodedAudio_int < 0) |
| { |
| printf(" Decoder error in client %d \n", receiverIdx + 1); |
| return -1; |
| } |
| lenDecodedAudio = static_cast<size_t>(lenDecodedAudio_int); |
| |
| if(encoderSampRate[senderIdx] == 16000) |
| { |
| WebRtcSpl_UpsampleBy2(audioBuff60ms, lenDecodedAudio, resampledAudio60ms, |
| resamplerState[receiverIdx]); |
| if (fwrite(resampledAudio60ms, sizeof(short), lenDecodedAudio << 1, |
| outFile[receiverIdx]) != |
| lenDecodedAudio << 1) { |
| return -1; |
| } |
| } |
| else |
| { |
| if (fwrite(audioBuff60ms, sizeof(short), lenDecodedAudio, |
| outFile[receiverIdx]) != |
| lenDecodedAudio) { |
| return -1; |
| } |
| } |
| num10ms[senderIdx] = 0; |
| } |
| //} |
| //} |
| } |
| } |
| } |