1 /* 2 ** Copyright 2003-2010, VisualOn, Inc. 3 ** 4 ** Licensed under the Apache License, Version 2.0 (the "License"); 5 ** you may not use this file except in compliance with the License. 6 ** You may obtain a copy of the License at 7 ** 8 ** http://www.apache.org/licenses/LICENSE-2.0 9 ** 10 ** Unless required by applicable law or agreed to in writing, software 11 ** distributed under the License is distributed on an "AS IS" BASIS, 12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 ** See the License for the specific language governing permissions and 14 ** limitations under the License. 15 */ 16 /******************************************************************************* 17 File: psy_main.c 18 19 Content: Psychoacoustic major functions 20 21 *******************************************************************************/ 22 23 #include "typedef.h" 24 #include "basic_op.h" 25 #include "oper_32b.h" 26 #include "psy_const.h" 27 #include "block_switch.h" 28 #include "transform.h" 29 #include "spreading.h" 30 #include "pre_echo_control.h" 31 #include "band_nrg.h" 32 #include "psy_configuration.h" 33 #include "psy_data.h" 34 #include "ms_stereo.h" 35 #include "interface.h" 36 #include "psy_main.h" 37 #include "grp_data.h" 38 #include "tns_func.h" 39 #include "memalign.h" 40 41 #define UNUSED(x) (void)(x) 42 43 /* long start short stop */ 44 static Word16 blockType2windowShape[] = {KBD_WINDOW,SINE_WINDOW,SINE_WINDOW,KBD_WINDOW}; 45 46 /* 47 forward definitions 48 */ 49 static Word16 advancePsychLong(PSY_DATA* psyData, 50 TNS_DATA* tnsData, 51 PSY_CONFIGURATION_LONG *hPsyConfLong, 52 PSY_OUT_CHANNEL* psyOutChannel, 53 Word32 *pScratchTns, 54 const TNS_DATA *tnsData2, 55 const Word16 ch); 56 57 static Word16 advancePsychLongMS (PSY_DATA psyData[MAX_CHANNELS], 58 const PSY_CONFIGURATION_LONG *hPsyConfLong); 59 60 static Word16 advancePsychShort(PSY_DATA* psyData, 61 TNS_DATA* tnsData, 62 const PSY_CONFIGURATION_SHORT *hPsyConfShort, 63 PSY_OUT_CHANNEL* psyOutChannel, 64 Word32 *pScratchTns, 65 const TNS_DATA *tnsData2, 66 const Word16 ch); 67 68 static Word16 advancePsychShortMS (PSY_DATA psyData[MAX_CHANNELS], 69 const PSY_CONFIGURATION_SHORT *hPsyConfShort); 70 71 72 /***************************************************************************** 73 * 74 * function name: PsyNew 75 * description: allocates memory for psychoacoustic 76 * returns: an error code 77 * input: pointer to a psych handle 78 * 79 *****************************************************************************/ 80 Word16 PsyNew(PSY_KERNEL *hPsy, Word32 nChan, VO_MEM_OPERATOR *pMemOP) 81 { 82 Word16 i; 83 Word32 *mdctSpectrum; 84 Word32 *scratchTNS; 85 Word16 *mdctDelayBuffer; 86 87 mdctSpectrum = (Word32 *)mem_malloc(pMemOP, nChan * FRAME_LEN_LONG * sizeof(Word32), 32, VO_INDEX_ENC_AAC); 88 if(NULL == mdctSpectrum) 89 return 1; 90 91 scratchTNS = (Word32 *)mem_malloc(pMemOP, nChan * FRAME_LEN_LONG * sizeof(Word32), 32, VO_INDEX_ENC_AAC); 92 if(NULL == scratchTNS) 93 { 94 return 1; 95 } 96 97 mdctDelayBuffer = (Word16 *)mem_malloc(pMemOP, nChan * BLOCK_SWITCHING_OFFSET * sizeof(Word16), 32, VO_INDEX_ENC_AAC); 98 if(NULL == mdctDelayBuffer) 99 { 100 return 1; 101 } 102 103 for (i=0; i<nChan; i++){ 104 hPsy->psyData[i].mdctDelayBuffer = mdctDelayBuffer + i*BLOCK_SWITCHING_OFFSET; 105 hPsy->psyData[i].mdctSpectrum = mdctSpectrum + i*FRAME_LEN_LONG; 106 } 107 108 hPsy->pScratchTns = scratchTNS; 109 110 return 0; 111 } 112 113 114 /***************************************************************************** 115 * 116 * function name: PsyDelete 117 * description: allocates memory for psychoacoustic 118 * returns: an error code 119 * 120 *****************************************************************************/ 121 Word16 PsyDelete(PSY_KERNEL *hPsy, VO_MEM_OPERATOR *pMemOP) 122 { 123 Word32 nch; 124 125 if(hPsy) 126 { 127 if(hPsy->psyData[0].mdctDelayBuffer) 128 mem_free(pMemOP, hPsy->psyData[0].mdctDelayBuffer, VO_INDEX_ENC_AAC); 129 130 if(hPsy->psyData[0].mdctSpectrum) 131 mem_free(pMemOP, hPsy->psyData[0].mdctSpectrum, VO_INDEX_ENC_AAC); 132 133 for (nch=0; nch<MAX_CHANNELS; nch++){ 134 hPsy->psyData[nch].mdctDelayBuffer = NULL; 135 hPsy->psyData[nch].mdctSpectrum = NULL; 136 } 137 138 if(hPsy->pScratchTns) 139 { 140 mem_free(pMemOP, hPsy->pScratchTns, VO_INDEX_ENC_AAC); 141 hPsy->pScratchTns = NULL; 142 } 143 } 144 145 return 0; 146 } 147 148 149 /***************************************************************************** 150 * 151 * function name: PsyOutNew 152 * description: allocates memory for psyOut struc 153 * returns: an error code 154 * input: pointer to a psych handle 155 * 156 *****************************************************************************/ 157 Word16 PsyOutNew(PSY_OUT *hPsyOut, VO_MEM_OPERATOR *pMemOP) 158 { 159 pMemOP->Set(VO_INDEX_ENC_AAC, hPsyOut, 0, sizeof(PSY_OUT)); 160 /* 161 alloc some more stuff, tbd 162 */ 163 return 0; 164 } 165 166 /***************************************************************************** 167 * 168 * function name: PsyOutDelete 169 * description: allocates memory for psychoacoustic 170 * returns: an error code 171 * 172 *****************************************************************************/ 173 Word16 PsyOutDelete(PSY_OUT *hPsyOut, VO_MEM_OPERATOR *pMemOP) 174 { 175 UNUSED(hPsyOut); 176 UNUSED(pMemOP); 177 178 return 0; 179 } 180 181 182 /***************************************************************************** 183 * 184 * function name: psyMainInit 185 * description: initializes psychoacoustic 186 * returns: an error code 187 * 188 *****************************************************************************/ 189 190 Word16 psyMainInit(PSY_KERNEL *hPsy, 191 Word32 sampleRate, 192 Word32 bitRate, 193 Word16 channels, 194 Word16 tnsMask, 195 Word16 bandwidth) 196 { 197 Word16 ch, err; 198 Word32 channelBitRate = bitRate/channels; 199 200 err = InitPsyConfigurationLong(channelBitRate, 201 sampleRate, 202 bandwidth, 203 &(hPsy->psyConfLong)); 204 205 if (!err) { 206 hPsy->sampleRateIdx = hPsy->psyConfLong.sampRateIdx; 207 err = InitTnsConfigurationLong(bitRate, sampleRate, channels, 208 &hPsy->psyConfLong.tnsConf, &hPsy->psyConfLong, tnsMask&2); 209 } 210 211 if (!err) 212 err = InitPsyConfigurationShort(channelBitRate, 213 sampleRate, 214 bandwidth, 215 &hPsy->psyConfShort); 216 if (!err) { 217 err = InitTnsConfigurationShort(bitRate, sampleRate, channels, 218 &hPsy->psyConfShort.tnsConf, &hPsy->psyConfShort, tnsMask&1); 219 } 220 221 if (!err) 222 for(ch=0;ch < channels;ch++){ 223 224 InitBlockSwitching(&hPsy->psyData[ch].blockSwitchingControl, 225 bitRate, channels); 226 227 InitPreEchoControl(hPsy->psyData[ch].sfbThresholdnm1, 228 hPsy->psyConfLong.sfbCnt, 229 hPsy->psyConfLong.sfbThresholdQuiet); 230 hPsy->psyData[ch].mdctScalenm1 = 0; 231 } 232 233 return(err); 234 } 235 236 /***************************************************************************** 237 * 238 * function name: psyMain 239 * description: psychoacoustic main function 240 * returns: an error code 241 * 242 * This function assumes that enough input data is in the modulo buffer. 243 * 244 *****************************************************************************/ 245 246 Word16 psyMain(Word16 nChannels, 247 ELEMENT_INFO *elemInfo, 248 Word16 *timeSignal, 249 PSY_DATA psyData[MAX_CHANNELS], 250 TNS_DATA tnsData[MAX_CHANNELS], 251 PSY_CONFIGURATION_LONG *hPsyConfLong, 252 PSY_CONFIGURATION_SHORT *hPsyConfShort, 253 PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], 254 PSY_OUT_ELEMENT *psyOutElement, 255 Word32 *pScratchTns, 256 Word32 sampleRate) 257 { 258 Word16 maxSfbPerGroup[MAX_CHANNELS]; 259 Word16 mdctScalingArray[MAX_CHANNELS]; 260 261 Word16 ch; /* counts through channels */ 262 Word16 sfb; /* counts through scalefactor bands */ 263 Word16 line; /* counts through lines */ 264 Word16 channels; 265 Word16 maxScale; 266 267 channels = elemInfo->nChannelsInEl; 268 maxScale = 0; 269 270 /* block switching */ 271 for(ch = 0; ch < channels; ch++) { 272 BlockSwitching(&psyData[ch].blockSwitchingControl, 273 timeSignal+elemInfo->ChannelIndex[ch], 274 sampleRate, 275 nChannels); 276 } 277 278 /* synch left and right block type */ 279 SyncBlockSwitching(&psyData[0].blockSwitchingControl, 280 &psyData[1].blockSwitchingControl, 281 channels); 282 283 /* transform 284 and get maxScale (max mdctScaling) for all channels */ 285 for(ch=0; ch<channels; ch++) { 286 Transform_Real(psyData[ch].mdctDelayBuffer, 287 timeSignal+elemInfo->ChannelIndex[ch], 288 nChannels, 289 psyData[ch].mdctSpectrum, 290 &(mdctScalingArray[ch]), 291 psyData[ch].blockSwitchingControl.windowSequence); 292 maxScale = max(maxScale, mdctScalingArray[ch]); 293 } 294 295 /* common scaling for all channels */ 296 for (ch=0; ch<channels; ch++) { 297 Word16 scaleDiff = maxScale - mdctScalingArray[ch]; 298 299 if (scaleDiff > 0) { 300 Word32 *Spectrum = psyData[ch].mdctSpectrum; 301 for(line=0; line<FRAME_LEN_LONG; line++) { 302 *Spectrum = (*Spectrum) >> scaleDiff; 303 Spectrum++; 304 } 305 } 306 psyData[ch].mdctScale = maxScale; 307 } 308 309 for (ch=0; ch<channels; ch++) { 310 311 if(psyData[ch].blockSwitchingControl.windowSequence != SHORT_WINDOW) { 312 /* update long block parameter */ 313 advancePsychLong(&psyData[ch], 314 &tnsData[ch], 315 hPsyConfLong, 316 &psyOutChannel[ch], 317 pScratchTns, 318 &tnsData[1 - ch], 319 ch); 320 321 /* determine maxSfb */ 322 for (sfb=hPsyConfLong->sfbCnt-1; sfb>=0; sfb--) { 323 for (line=hPsyConfLong->sfbOffset[sfb+1] - 1; line>=hPsyConfLong->sfbOffset[sfb]; line--) { 324 325 if (psyData[ch].mdctSpectrum[line] != 0) break; 326 } 327 if (line >= hPsyConfLong->sfbOffset[sfb]) break; 328 } 329 maxSfbPerGroup[ch] = sfb + 1; 330 331 /* Calc bandwise energies for mid and side channel 332 Do it only if 2 channels exist */ 333 334 if (ch == 1) 335 advancePsychLongMS(psyData, hPsyConfLong); 336 } 337 else { 338 advancePsychShort(&psyData[ch], 339 &tnsData[ch], 340 hPsyConfShort, 341 &psyOutChannel[ch], 342 pScratchTns, 343 &tnsData[1 - ch], 344 ch); 345 346 /* Calc bandwise energies for mid and side channel 347 Do it only if 2 channels exist */ 348 349 if (ch == 1) 350 advancePsychShortMS (psyData, hPsyConfShort); 351 } 352 } 353 354 /* group short data */ 355 for(ch=0; ch<channels; ch++) { 356 357 if (psyData[ch].blockSwitchingControl.windowSequence == SHORT_WINDOW) { 358 groupShortData(psyData[ch].mdctSpectrum, 359 pScratchTns, 360 &psyData[ch].sfbThreshold, 361 &psyData[ch].sfbEnergy, 362 &psyData[ch].sfbEnergyMS, 363 &psyData[ch].sfbSpreadedEnergy, 364 hPsyConfShort->sfbCnt, 365 hPsyConfShort->sfbOffset, 366 hPsyConfShort->sfbMinSnr, 367 psyOutElement->groupedSfbOffset[ch], 368 &maxSfbPerGroup[ch], 369 psyOutElement->groupedSfbMinSnr[ch], 370 psyData[ch].blockSwitchingControl.noOfGroups, 371 psyData[ch].blockSwitchingControl.groupLen); 372 } 373 } 374 375 376 #if (MAX_CHANNELS>1) 377 /* 378 stereo Processing 379 */ 380 if (channels == 2) { 381 psyOutElement->toolsInfo.msDigest = MS_NONE; 382 maxSfbPerGroup[0] = maxSfbPerGroup[1] = max(maxSfbPerGroup[0], maxSfbPerGroup[1]); 383 384 385 if (psyData[0].blockSwitchingControl.windowSequence != SHORT_WINDOW) 386 MsStereoProcessing(psyData[0].sfbEnergy.sfbLong, 387 psyData[1].sfbEnergy.sfbLong, 388 psyData[0].sfbEnergyMS.sfbLong, 389 psyData[1].sfbEnergyMS.sfbLong, 390 psyData[0].mdctSpectrum, 391 psyData[1].mdctSpectrum, 392 psyData[0].sfbThreshold.sfbLong, 393 psyData[1].sfbThreshold.sfbLong, 394 psyData[0].sfbSpreadedEnergy.sfbLong, 395 psyData[1].sfbSpreadedEnergy.sfbLong, 396 (Word16*)&psyOutElement->toolsInfo.msDigest, 397 (Word16*)psyOutElement->toolsInfo.msMask, 398 hPsyConfLong->sfbCnt, 399 hPsyConfLong->sfbCnt, 400 maxSfbPerGroup[0], 401 (const Word16*)hPsyConfLong->sfbOffset); 402 else 403 MsStereoProcessing(psyData[0].sfbEnergy.sfbLong, 404 psyData[1].sfbEnergy.sfbLong, 405 psyData[0].sfbEnergyMS.sfbLong, 406 psyData[1].sfbEnergyMS.sfbLong, 407 psyData[0].mdctSpectrum, 408 psyData[1].mdctSpectrum, 409 psyData[0].sfbThreshold.sfbLong, 410 psyData[1].sfbThreshold.sfbLong, 411 psyData[0].sfbSpreadedEnergy.sfbLong, 412 psyData[1].sfbSpreadedEnergy.sfbLong, 413 (Word16*)&psyOutElement->toolsInfo.msDigest, 414 (Word16*)psyOutElement->toolsInfo.msMask, 415 psyData[0].blockSwitchingControl.noOfGroups*hPsyConfShort->sfbCnt, 416 hPsyConfShort->sfbCnt, 417 maxSfbPerGroup[0], 418 (const Word16*)psyOutElement->groupedSfbOffset[0]); 419 } 420 421 #endif /* (MAX_CHANNELS>1) */ 422 423 /* 424 build output 425 */ 426 for(ch=0;ch<channels;ch++) { 427 428 if (psyData[ch].blockSwitchingControl.windowSequence != SHORT_WINDOW) 429 BuildInterface(psyData[ch].mdctSpectrum, 430 psyData[ch].mdctScale, 431 &psyData[ch].sfbThreshold, 432 &psyData[ch].sfbEnergy, 433 &psyData[ch].sfbSpreadedEnergy, 434 psyData[ch].sfbEnergySum, 435 psyData[ch].sfbEnergySumMS, 436 psyData[ch].blockSwitchingControl.windowSequence, 437 blockType2windowShape[psyData[ch].blockSwitchingControl.windowSequence], 438 hPsyConfLong->sfbCnt, 439 hPsyConfLong->sfbOffset, 440 maxSfbPerGroup[ch], 441 hPsyConfLong->sfbMinSnr, 442 psyData[ch].blockSwitchingControl.noOfGroups, 443 psyData[ch].blockSwitchingControl.groupLen, 444 &psyOutChannel[ch]); 445 else 446 BuildInterface(psyData[ch].mdctSpectrum, 447 psyData[ch].mdctScale, 448 &psyData[ch].sfbThreshold, 449 &psyData[ch].sfbEnergy, 450 &psyData[ch].sfbSpreadedEnergy, 451 psyData[ch].sfbEnergySum, 452 psyData[ch].sfbEnergySumMS, 453 SHORT_WINDOW, 454 SINE_WINDOW, 455 psyData[0].blockSwitchingControl.noOfGroups*hPsyConfShort->sfbCnt, 456 psyOutElement->groupedSfbOffset[ch], 457 maxSfbPerGroup[ch], 458 psyOutElement->groupedSfbMinSnr[ch], 459 psyData[ch].blockSwitchingControl.noOfGroups, 460 psyData[ch].blockSwitchingControl.groupLen, 461 &psyOutChannel[ch]); 462 } 463 464 return(0); /* no error */ 465 } 466 467 /***************************************************************************** 468 * 469 * function name: advancePsychLong 470 * description: psychoacoustic for long blocks 471 * 472 *****************************************************************************/ 473 474 static Word16 advancePsychLong(PSY_DATA* psyData, 475 TNS_DATA* tnsData, 476 PSY_CONFIGURATION_LONG *hPsyConfLong, 477 PSY_OUT_CHANNEL* psyOutChannel, 478 Word32 *pScratchTns, 479 const TNS_DATA* tnsData2, 480 const Word16 ch) 481 { 482 Word32 i; 483 Word32 normEnergyShift = (psyData->mdctScale + 1) << 1; /* in reference code, mdct spectrum must be multipied with 2, so +1 */ 484 Word32 clipEnergy = hPsyConfLong->clipEnergy >> normEnergyShift; 485 Word32 *data0, *data1, tdata; 486 487 /* low pass */ 488 data0 = psyData->mdctSpectrum + hPsyConfLong->lowpassLine; 489 for(i=hPsyConfLong->lowpassLine; i<FRAME_LEN_LONG; i++) { 490 *data0++ = 0; 491 } 492 493 /* Calc sfb-bandwise mdct-energies for left and right channel */ 494 CalcBandEnergy( psyData->mdctSpectrum, 495 hPsyConfLong->sfbOffset, 496 hPsyConfLong->sfbActive, 497 psyData->sfbEnergy.sfbLong, 498 &psyData->sfbEnergySum.sfbLong); 499 500 /* 501 TNS detect 502 */ 503 TnsDetect(tnsData, 504 hPsyConfLong->tnsConf, 505 pScratchTns, 506 (const Word16*)hPsyConfLong->sfbOffset, 507 psyData->mdctSpectrum, 508 0, 509 psyData->blockSwitchingControl.windowSequence, 510 psyData->sfbEnergy.sfbLong); 511 512 /* TnsSync */ 513 if (ch == 1) { 514 TnsSync(tnsData, 515 tnsData2, 516 hPsyConfLong->tnsConf, 517 0, 518 psyData->blockSwitchingControl.windowSequence); 519 } 520 521 /* Tns Encoder */ 522 TnsEncode(&psyOutChannel->tnsInfo, 523 tnsData, 524 hPsyConfLong->sfbCnt, 525 hPsyConfLong->tnsConf, 526 hPsyConfLong->lowpassLine, 527 psyData->mdctSpectrum, 528 0, 529 psyData->blockSwitchingControl.windowSequence); 530 531 /* first part of threshold calculation */ 532 data0 = psyData->sfbEnergy.sfbLong; 533 data1 = psyData->sfbThreshold.sfbLong; 534 for (i=hPsyConfLong->sfbCnt; i; i--) { 535 tdata = L_mpy_ls(*data0++, hPsyConfLong->ratio); 536 *data1++ = min(tdata, clipEnergy); 537 } 538 539 /* Calc sfb-bandwise mdct-energies for left and right channel again */ 540 if (tnsData->dataRaw.tnsLong.subBlockInfo.tnsActive!=0) { 541 Word16 tnsStartBand = hPsyConfLong->tnsConf.tnsStartBand; 542 CalcBandEnergy( psyData->mdctSpectrum, 543 hPsyConfLong->sfbOffset+tnsStartBand, 544 hPsyConfLong->sfbActive - tnsStartBand, 545 psyData->sfbEnergy.sfbLong+tnsStartBand, 546 &psyData->sfbEnergySum.sfbLong); 547 548 data0 = psyData->sfbEnergy.sfbLong; 549 tdata = psyData->sfbEnergySum.sfbLong; 550 for (i=0; i<tnsStartBand; i++) 551 tdata += *data0++; 552 553 psyData->sfbEnergySum.sfbLong = tdata; 554 } 555 556 557 /* spreading energy */ 558 SpreadingMax(hPsyConfLong->sfbCnt, 559 hPsyConfLong->sfbMaskLowFactor, 560 hPsyConfLong->sfbMaskHighFactor, 561 psyData->sfbThreshold.sfbLong); 562 563 /* threshold in quiet */ 564 data0 = psyData->sfbThreshold.sfbLong; 565 data1 = hPsyConfLong->sfbThresholdQuiet; 566 for (i=hPsyConfLong->sfbCnt; i; i--) 567 { 568 *data0 = max(*data0, (*data1 >> normEnergyShift)); 569 data0++; data1++; 570 } 571 572 /* preecho control */ 573 if (psyData->blockSwitchingControl.windowSequence == STOP_WINDOW) { 574 data0 = psyData->sfbThresholdnm1; 575 for (i=hPsyConfLong->sfbCnt; i; i--) { 576 *data0++ = MAX_32; 577 } 578 psyData->mdctScalenm1 = 0; 579 } 580 581 PreEchoControl( psyData->sfbThresholdnm1, 582 hPsyConfLong->sfbCnt, 583 hPsyConfLong->maxAllowedIncreaseFactor, 584 hPsyConfLong->minRemainingThresholdFactor, 585 psyData->sfbThreshold.sfbLong, 586 psyData->mdctScale, 587 psyData->mdctScalenm1); 588 psyData->mdctScalenm1 = psyData->mdctScale; 589 590 591 if (psyData->blockSwitchingControl.windowSequence== START_WINDOW) { 592 data0 = psyData->sfbThresholdnm1; 593 for (i=hPsyConfLong->sfbCnt; i; i--) { 594 *data0++ = MAX_32; 595 } 596 psyData->mdctScalenm1 = 0; 597 } 598 599 /* apply tns mult table on cb thresholds */ 600 ApplyTnsMultTableToRatios(hPsyConfLong->tnsConf.tnsRatioPatchLowestCb, 601 hPsyConfLong->tnsConf.tnsStartBand, 602 tnsData->dataRaw.tnsLong.subBlockInfo, 603 psyData->sfbThreshold.sfbLong); 604 605 606 /* spreaded energy */ 607 data0 = psyData->sfbSpreadedEnergy.sfbLong; 608 data1 = psyData->sfbEnergy.sfbLong; 609 for (i=hPsyConfLong->sfbCnt; i; i--) { 610 //psyData->sfbSpreadedEnergy.sfbLong[i] = psyData->sfbEnergy.sfbLong[i]; 611 *data0++ = *data1++; 612 } 613 614 /* spreading energy */ 615 SpreadingMax(hPsyConfLong->sfbCnt, 616 hPsyConfLong->sfbMaskLowFactorSprEn, 617 hPsyConfLong->sfbMaskHighFactorSprEn, 618 psyData->sfbSpreadedEnergy.sfbLong); 619 620 return 0; 621 } 622 623 /***************************************************************************** 624 * 625 * function name: advancePsychLongMS 626 * description: update mdct-energies for left add or minus right channel 627 * for long block 628 * 629 *****************************************************************************/ 630 static Word16 advancePsychLongMS (PSY_DATA psyData[MAX_CHANNELS], 631 const PSY_CONFIGURATION_LONG *hPsyConfLong) 632 { 633 CalcBandEnergyMS(psyData[0].mdctSpectrum, 634 psyData[1].mdctSpectrum, 635 hPsyConfLong->sfbOffset, 636 hPsyConfLong->sfbActive, 637 psyData[0].sfbEnergyMS.sfbLong, 638 &psyData[0].sfbEnergySumMS.sfbLong, 639 psyData[1].sfbEnergyMS.sfbLong, 640 &psyData[1].sfbEnergySumMS.sfbLong); 641 642 return 0; 643 } 644 645 646 /***************************************************************************** 647 * 648 * function name: advancePsychShort 649 * description: psychoacoustic for short blocks 650 * 651 *****************************************************************************/ 652 653 static Word16 advancePsychShort(PSY_DATA* psyData, 654 TNS_DATA* tnsData, 655 const PSY_CONFIGURATION_SHORT *hPsyConfShort, 656 PSY_OUT_CHANNEL* psyOutChannel, 657 Word32 *pScratchTns, 658 const TNS_DATA *tnsData2, 659 const Word16 ch) 660 { 661 Word32 w; 662 Word32 normEnergyShift = (psyData->mdctScale + 1) << 1; /* in reference code, mdct spectrum must be multipied with 2, so +1 */ 663 Word32 clipEnergy = hPsyConfShort->clipEnergy >> normEnergyShift; 664 Word32 wOffset = 0; 665 Word32 *data0; 666 const Word32 *data1; 667 668 for(w = 0; w < TRANS_FAC; w++) { 669 Word32 i, tdata; 670 671 /* low pass */ 672 data0 = psyData->mdctSpectrum + wOffset + hPsyConfShort->lowpassLine; 673 for(i=hPsyConfShort->lowpassLine; i<FRAME_LEN_SHORT; i++){ 674 *data0++ = 0; 675 } 676 677 /* Calc sfb-bandwise mdct-energies for left and right channel */ 678 CalcBandEnergy( psyData->mdctSpectrum+wOffset, 679 hPsyConfShort->sfbOffset, 680 hPsyConfShort->sfbActive, 681 psyData->sfbEnergy.sfbShort[w], 682 &psyData->sfbEnergySum.sfbShort[w]); 683 /* 684 TNS 685 */ 686 TnsDetect(tnsData, 687 hPsyConfShort->tnsConf, 688 pScratchTns, 689 (const Word16*)hPsyConfShort->sfbOffset, 690 psyData->mdctSpectrum+wOffset, 691 w, 692 psyData->blockSwitchingControl.windowSequence, 693 psyData->sfbEnergy.sfbShort[w]); 694 695 /* TnsSync */ 696 if (ch == 1) { 697 TnsSync(tnsData, 698 tnsData2, 699 hPsyConfShort->tnsConf, 700 w, 701 psyData->blockSwitchingControl.windowSequence); 702 } 703 704 TnsEncode(&psyOutChannel->tnsInfo, 705 tnsData, 706 hPsyConfShort->sfbCnt, 707 hPsyConfShort->tnsConf, 708 hPsyConfShort->lowpassLine, 709 psyData->mdctSpectrum+wOffset, 710 w, 711 psyData->blockSwitchingControl.windowSequence); 712 713 /* first part of threshold calculation */ 714 data0 = psyData->sfbThreshold.sfbShort[w]; 715 data1 = psyData->sfbEnergy.sfbShort[w]; 716 for (i=hPsyConfShort->sfbCnt; i; i--) { 717 tdata = L_mpy_ls(*data1++, hPsyConfShort->ratio); 718 *data0++ = min(tdata, clipEnergy); 719 } 720 721 /* Calc sfb-bandwise mdct-energies for left and right channel again */ 722 if (tnsData->dataRaw.tnsShort.subBlockInfo[w].tnsActive != 0) { 723 Word16 tnsStartBand = hPsyConfShort->tnsConf.tnsStartBand; 724 CalcBandEnergy( psyData->mdctSpectrum+wOffset, 725 hPsyConfShort->sfbOffset+tnsStartBand, 726 (hPsyConfShort->sfbActive - tnsStartBand), 727 psyData->sfbEnergy.sfbShort[w]+tnsStartBand, 728 &psyData->sfbEnergySum.sfbShort[w]); 729 730 tdata = psyData->sfbEnergySum.sfbShort[w]; 731 data0 = psyData->sfbEnergy.sfbShort[w]; 732 for (i=tnsStartBand; i; i--) 733 tdata += *data0++; 734 735 psyData->sfbEnergySum.sfbShort[w] = tdata; 736 } 737 738 /* spreading */ 739 SpreadingMax(hPsyConfShort->sfbCnt, 740 hPsyConfShort->sfbMaskLowFactor, 741 hPsyConfShort->sfbMaskHighFactor, 742 psyData->sfbThreshold.sfbShort[w]); 743 744 745 /* threshold in quiet */ 746 data0 = psyData->sfbThreshold.sfbShort[w]; 747 data1 = hPsyConfShort->sfbThresholdQuiet; 748 for (i=hPsyConfShort->sfbCnt; i; i--) 749 { 750 *data0 = max(*data0, (*data1 >> normEnergyShift)); 751 752 data0++; data1++; 753 } 754 755 756 /* preecho */ 757 PreEchoControl( psyData->sfbThresholdnm1, 758 hPsyConfShort->sfbCnt, 759 hPsyConfShort->maxAllowedIncreaseFactor, 760 hPsyConfShort->minRemainingThresholdFactor, 761 psyData->sfbThreshold.sfbShort[w], 762 psyData->mdctScale, 763 w==0 ? psyData->mdctScalenm1 : psyData->mdctScale); 764 765 /* apply tns mult table on cb thresholds */ 766 ApplyTnsMultTableToRatios( hPsyConfShort->tnsConf.tnsRatioPatchLowestCb, 767 hPsyConfShort->tnsConf.tnsStartBand, 768 tnsData->dataRaw.tnsShort.subBlockInfo[w], 769 psyData->sfbThreshold.sfbShort[w]); 770 771 /* spreaded energy */ 772 data0 = psyData->sfbSpreadedEnergy.sfbShort[w]; 773 data1 = psyData->sfbEnergy.sfbShort[w]; 774 for (i=hPsyConfShort->sfbCnt; i; i--) { 775 *data0++ = *data1++; 776 } 777 SpreadingMax(hPsyConfShort->sfbCnt, 778 hPsyConfShort->sfbMaskLowFactorSprEn, 779 hPsyConfShort->sfbMaskHighFactorSprEn, 780 psyData->sfbSpreadedEnergy.sfbShort[w]); 781 782 wOffset += FRAME_LEN_SHORT; 783 } /* for TRANS_FAC */ 784 785 psyData->mdctScalenm1 = psyData->mdctScale; 786 787 return 0; 788 } 789 790 /***************************************************************************** 791 * 792 * function name: advancePsychShortMS 793 * description: update mdct-energies for left add or minus right channel 794 * for short block 795 * 796 *****************************************************************************/ 797 static Word16 advancePsychShortMS (PSY_DATA psyData[MAX_CHANNELS], 798 const PSY_CONFIGURATION_SHORT *hPsyConfShort) 799 { 800 Word32 w, wOffset; 801 wOffset = 0; 802 for(w=0; w<TRANS_FAC; w++) { 803 CalcBandEnergyMS(psyData[0].mdctSpectrum+wOffset, 804 psyData[1].mdctSpectrum+wOffset, 805 hPsyConfShort->sfbOffset, 806 hPsyConfShort->sfbActive, 807 psyData[0].sfbEnergyMS.sfbShort[w], 808 &psyData[0].sfbEnergySumMS.sfbShort[w], 809 psyData[1].sfbEnergyMS.sfbShort[w], 810 &psyData[1].sfbEnergySumMS.sfbShort[w]); 811 wOffset += FRAME_LEN_SHORT; 812 } 813 814 return 0; 815 } 816