2 /*
3 Copyright (c) 2016, Texas Instruments Incorporated - http://www.ti.com/
4 All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the
16 * distribution.
17 *
18 * Neither the name of Texas Instruments Incorporated nor the names of
19 * its contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 *
34 */
36 //
37 //
38 // Performance Audio Framework Series 3 -- Audio Stream Processing Definitions
39 //
40 //
41 //
43 #include "fwkPort.h"
45 #include <xdc/std.h>
47 //#include <mem.h>
48 #include <xdc/runtime/Log.h>
49 #include <xdc/runtime/Memory.h>
50 #include <xdc/runtime/Error.h>
51 #include <xdc/runtime/IHeap.h>
52 #include <ti/sysbios/heaps/HeapMem.h>
54 #include "dbgBenchmark.h" // PCM high-sampling rate + SRC + CAR benchmarking
55 //
56 // Performing PCM high-sampling rate + SRC + CAR benchmarking
57 //
58 #ifdef _ENABLE_BENCHMARK_PCMHSR_SRC_CAR_
59 #define PROFILER
60 #endif
62 #ifdef PROFILER
63 #include <ti/sysbios/knl/Task.h>
64 #include "ti/sysbios/knl/Clock.h"
65 #include "xdc/runtime/Timestamp.h"
66 #include "ti/sysbios/utils/Load.h"
68 #ifndef MAX_NUM
69 #define MAX_NUM 28515
70 #define NUM_ASP_PROFILE 0 // Profile CAR; As we have PCM->SRC(0)->CAR(1)->PCE
71 #endif
72 UInt32 profile_array_dsp_cycles[MAX_NUM];
73 UInt32 profile_array_dsp_cpuload[MAX_NUM];
74 UInt32 profile_index = 0; // Array index
75 UInt32 start_profiling = 0; // Flag
76 UInt32 currentAspCount = 0; // ASP number in chain starting from 0
77 UInt32 aspNumberToProfile = NUM_ASP_PROFILE; // ASP number in chain starting from 0
78 volatile UInt32 time32_1, time32_2;
79 #endif
81 //
82 #include "asp0.h"
83 //#include <paf_alg.h>
84 //#include <pafhjt.h>
86 #include <acp.h>
88 #include "logp.h"
92 //
93 // Audio Stream Processing Chain Function - Initialization
94 //
95 // Name: PAF_ASP_chainInit_
96 // Purpose: Initialize an ASP Chain by linking all elements of an
97 // initialization array onto it. If this is the first audio
98 // stream, perform base initialization of the ASP Chain, but
99 // otherwise do not.
100 // From: AST Parameter Chain Function -> chainInit
101 // Uses: AST Parameter Chain Function -> chainLink
102 // States: None.
103 // Return: ASP Chain.
104 // Trace: None.
105 //
107 PAF_ASP_Chain *
108 PAF_ASP_chainInit_ (
109 PAF_ASP_Chain *this,
110 const struct PAF_ASP_ChainFxns *fxns,
111 HeapMem_Handle heap, //int heap,
112 Uns stream,
113 ACP_Handle acp,
114 LOG_Obj *log,
115 const PAF_ASP_LinkInit *pInit,
116 PAF_ASP_Chain *from,
117 IALG_MemRec *common,
118 PAF_IALG_Config *pafConfig)
119 {
120 if (stream) {
121 this->fxns = fxns;
122 this->head = NULL;
123 this->stream = stream;
124 this->acp = acp;
125 this->log = log;
126 }
128 for ( ; pInit && pInit->thisCode.full; pInit++)
129 if (! this->fxns->chainLink (this, heap, pInit, from, common, pafConfig))
130 return NULL;
132 return this;
133 }
135 //
136 // Audio Stream Processing Chain Function - Link
137 //
138 // Name: PAF_ASP_chainLink_
139 // Purpose: Link an element onto an ASP Chain:
140 // (1) Allocate memory for the link, and
141 // (2) For the first gear, create the data for the link, but
142 // (3) For other than the first gear, simply link the data already
143 // created in the previous gear.
144 // From: AST Parameter Chain Function -> chainInit
145 // Uses: See code.
146 // States: None.
147 // Return: Success: ASP Chain.
148 // Failure: Null.
149 // Trace: Message Log "trace" in Debug Project Configuration reports:
150 // * Memory allocation errors.
151 // * Data creation errors.
152 // * Data linking errors.
153 //
156 PAF_ASP_Chain *
157 PAF_ASP_chainLink_ (
158 PAF_ASP_Chain *this,
159 HeapMem_Handle heap, //int heap,
160 const PAF_ASP_LinkInit *pInit,
161 PAF_ASP_Chain *from,
162 IALG_MemRec *common,
163 PAF_IALG_Config *pafConfig)
164 {
165 PAF_ASP_Link *pLink;
166 Error_Block eb;
168 if (! this || ! pInit)
169 return this;
171 // Initialize error block
172 Error_init(&eb);
174 //if (! (pLink = MEM_alloc (heap, sizeof(PAF_ASP_Link), 4))) {
175 if (!(pLink = Memory_alloc((IHeap_Handle)heap, sizeof(PAF_ASP_Link), 4, &eb))) {
176 if (this->log)
177 LOG_printf(this->log, "AS%d: ASP code 0x%08x alloc failure",
178 this->stream, pInit->thisCode.full);
179 return NULL;
180 }
182 if (! from) {
183 if (! this->fxns->linkData(pLink, pInit, this->stream, this->acp,
184 this->log,common, pafConfig)) {
185 if (this->log)
186 LOG_printf(this->log, "AS%d: ASP code 0x%08x link-init failure",
187 this->stream, pInit->thisCode.full);
188 return NULL;
189 }
190 }
191 else {
192 if (! this->fxns->linkCopy(pLink, pInit, from->head)) {
193 if (this->log)
194 LOG_printf(this->log, "AS%d: ASP code 0x%08x link-copy failure",
195 this->stream, pInit->thisCode.full);
196 return NULL;
197 }
198 }
200 {
201 PAF_ASP_Link **ppLink;
202 for (ppLink=&this->head; *ppLink; ppLink=&(*ppLink)->next)
203 if ((*ppLink)->code.full == pInit->linkCode.full)
204 break;
205 pLink->next = *ppLink;
206 *ppLink = pLink;
207 }
209 return this;
210 }
212 //
213 // Audio Stream Processing Chain Function - Find
214 //
215 // Name: PAF_ASP_chainFind_
216 // Purpose: Find an element in an ASP Chain.
217 // From: AST Parameter Chain Function -> chainFind
218 // Uses: None.
219 // States: None.
220 // Return: Success (found): Pointer to element.
221 // Failure (not found): Null.
222 // Trace: None.
223 //
225 PAF_ASP_Link *
226 PAF_ASP_chainFind_ (
227 PAF_ASP_Chain *this,
228 PAF_ASP_AlphaCode code)
229 {
230 PAF_ASP_Link *that = this->head;
232 for ( ; that; that = that->next) {
233 if (that->code.full == code.full)
234 break;
235 }
237 return that;
238 }
240 //
241 // Audio Stream Processing Chain Function - Reset
242 //
243 // Name: PAF_ASP_chainReset_
244 // Purpose: Reset an ASP Chain by invoking for each element:
245 // (1) The algorithm activation function (NOT PERFORMED), and
246 // (2) The algorithm reset function.
247 // From: AST Parameter Chain Function -> chainReset
248 // Uses: See code.
249 // States: None.
250 // Return: 0 on success.
251 // Error number reported by ASP Reset Function on failure.
252 // Trace: Message Log "trace" in Debug Project Configuration reports:
253 // * ASP Reset Function errors.
254 //
256 Int
257 PAF_ASP_chainReset_ (PAF_ASP_Chain *this, PAF_AudioFrame *pAudioFrame)
258 {
259 Int errno;
261 PAF_ASP_Link *pLink;
263 for (pLink=this->head; pLink; pLink=pLink->next) {
264 ASP_Handle alg = pLink->alg;
265 #if 0
266 /* ASP Algorithms are self-activating and not framework-activated */
267 if (((ALG_Handle )alg)->fxns->algActivate)
268 ((ALG_Handle )alg)->fxns->algActivate (((ALG_Handle )alg));
269 #endif
270 if (alg->fxns->reset && (errno = alg->fxns->reset(alg, pAudioFrame))) {
271 if (this->log) {
272 LOG_printf(this->log, "AS%d: ASP code 0x%08x reset error",
273 this->stream, pLink->code.full);
274 LOG_printf(this->log, "AS%d: errno = 0x%08x",
275 this->stream, errno);
276 }
277 return errno;
278 }
279 }
281 return 0;
282 }
284 //
285 // Audio Stream Processing Chain Function - Apply
286 //
287 // Name: PAF_ASP_chainApply_
288 // Purpose: Apply an ASP Chain by invoking for each:
289 // (1) The algorithm apply function.
290 // From: AST Parameter Chain Function -> chainApply
291 // Uses: See code.
292 // States: None.
293 // Return: 0 on success.
294 // Error number reported by ASP Apply Function on failure.
295 // Trace: Message Log "trace" in Debug Project Configuration reports:
296 // * ASP Apply Function errors.
297 //
299 Int
300 PAF_ASP_chainApply_ (PAF_ASP_Chain *this, PAF_AudioFrame *pAudioFrame)
301 {
302 Int errno;
303 int i = 0;
305 PAF_ASP_Link *pLink;
307 for (pLink=this->head; pLink; pLink=pLink->next)
308 {
309 ASP_Handle alg = pLink->alg;
311 i++;
312 if (this->log)
313 {
314 LOG_printf(&trace, "PAF_ASP_chainApply_: AS_%d. link %d. alg: 0x%x.",
315 this->stream, i, alg);
316 }
317 Log_info3("PAF_ASP_chainApply_: AS_%d. link %d. alg: 0x%x.", this->stream, i, (IArg)alg);
319 if (alg->fxns->apply /*&& (errno = alg->fxns->apply(alg, pAudioFrame))*/)
320 {
322 #ifdef PROFILER
323 if (aspNumberToProfile == currentAspCount) // only profile the selected ASP
324 {
325 time32_1 = Timestamp_get32();
326 }
327 #endif
328 errno = alg->fxns->apply(alg, pAudioFrame);
330 #ifdef PROFILER
331 if (aspNumberToProfile == currentAspCount) // only profile the selected ASP
332 {
333 time32_2 = Timestamp_get32();
334 //Load_Stat stat;
335 //Load_getTaskLoad (Task_getIdleTask(), &stat);
336 //UInt32 intLoad = Load_calculateLoad (&stat);
337 if (start_profiling == 1)
338 {
339 if (profile_index < MAX_NUM)
340 {
341 profile_array_dsp_cycles[profile_index] = (time32_2 - time32_1);
342 //profile_array_dsp_cpuload[profile_index] = (100 - intLoad);
343 profile_array_dsp_cpuload[profile_index] = Load_getCPULoad();
344 profile_index++;
345 }
346 else
347 {
348 //SW_BREAKPOINT;
349 }
350 }
352 //TRACE_TERSE1("profiler: Timestamp_get32() cycles: %u", (time32_2 - time32_1) * factor);
353 //TRACE_TERSE2("profiler: CPU load: idle: %d other: %d", intLoad, (100 - intLoad));
354 }
355 // increase ASP count
356 currentAspCount++;
357 #endif
359 if (errno && this->log)
360 {
361 LOG_printf(this->log, "AS%d: ASP code 0x%08x apply error 0x%x.",
362 this->stream, pLink->code.full, errno);
363 LOG_printf(&trace, "AS%d: ASP code 0x%08x apply error 0x%x.",
364 this->stream, pLink->code.full, errno);
365 #ifdef PROFILER
366 // Reset ASP count for next frame
367 currentAspCount = 0;
368 #endif
369 return errno;
370 }
371 }
372 }
373 #ifdef PROFILER
374 // Reset ASP count for next frame
375 currentAspCount = 0;
376 #endif
378 return 0;
379 }
381 //
382 // Audio Stream Processing Chain Function - Final
383 //
384 // Name: PAF_ASP_chainFinal_
385 // Purpose: Finalize an ASP Chain by invoking for each:
386 // (1) The algorithm final function (NOT PERFORMED), and
387 // (2) The algorithm deactivation function.
388 // From: AST Parameter Chain Function -> chainFinal
389 // Uses: See code.
390 // States: None.
391 // Return: 0 on success.
392 // Error number reported by ASP Final Function on failure.
393 // Trace: Message Log "trace" in Debug Project Configuration reports:
394 // * ASP Final Function errors.
395 //
396 // Note: In Audio Framework #2, PAF_ASP_FINAL is not defined and there
397 // are no Final Functions supplied with ASP Algorithms.
399 Int
400 PAF_ASP_chainFinal_ (PAF_ASP_Chain *this, PAF_AudioFrame *pAudioFrame)
401 {
402 #ifdef PAF_ASP_FINAL
403 Int errno;
404 #endif /* PAF_ASP_FINAL */
406 PAF_ASP_Link *pLink;
408 for (pLink=this->head; pLink; pLink=pLink->next) {
409 ASP_Handle alg = pLink->alg;
410 #ifdef PAF_ASP_FINAL
411 if (alg->fxns->final && (errno = alg->fxns->final(alg, pAudioFrame))) {
412 if (this->log) {
413 LOG_printf(this->log, "AS%d: ASP code 0x%08x final error",
414 this->stream, pLink->code.full);
415 LOG_printf(this->log, "AS%d: errno = 0x%08x",
416 this->stream, errno);
417 }
418 return errno;
419 }
420 #endif /* PAF_ASP_FINAL */
421 #if 1
422 /* ASP Algorithms are self-deactivating and framework-deactivated */
423 if (((ALG_Handle )alg)->fxns->algDeactivate)
424 ((ALG_Handle )alg)->fxns->algDeactivate (((ALG_Handle )alg));
425 #endif
426 }
428 return 0;
429 }
431 //
432 // Audio Stream Processing Chain Function - Link Data
433 //
434 // Name: PAF_ASP_linkData
435 // Purpose: Create the data for a chain link:
436 // (1) Perform beta unit relocation,
437 // (2) Instantiate an algorithm, and
438 // (3) Attach the beta unit(s) of an algorithm to an ACP Algorithm
439 // instance.
440 // From: AST Parameter Chain Function -> linkData
441 // Uses: See code.
442 // States: None.
443 // Return: Null pointer on failure.
444 // Pointer to the chain link on success.
445 // Trace: Message Log "trace" in Debug Project Configuration reports:
446 // * Algorithm instance creation failure message.
447 // * Beta Unit initialization success message.
448 //
450 PAF_ASP_Link *
451 PAF_ASP_linkData (
452 PAF_ASP_Link *this,
453 const PAF_ASP_LinkInit *pInit,
454 Uns stream,
455 ACP_Handle acp,
456 LOG_Obj *log,
457 IALG_MemRec *common,
458 PAF_IALG_Config *pafConfig)
459 {
460 IALG_Status *pStatus;
462 ALG_Handle alg;
464 Int beta = pInit->thisCode.part.beta;
466 if (log)
467 LOG_printf(log, "AS%d: beta 0x%x initialization begins.", stream, beta);
468 {
469 ALG_Handle acpAlg = (ALG_Handle) acp;
470 Int betaPrimeBase;
471 Int betaPrimeOffset;
472 acpAlg->fxns->algControl (acpAlg, ACP_GETBETAPRIMEBASE,
473 (IALG_Status *) &betaPrimeBase);
474 acpAlg->fxns->algControl (acpAlg, ACP_GETBETAPRIMEOFFSET,
475 (IALG_Status *) &betaPrimeOffset);
476 if (beta >= betaPrimeBase)
477 beta += (stream - 1) * betaPrimeOffset;
478 }
480 this->next = NULL;
481 this->code = pInit->thisCode;
483 if (pInit->ialg_fxns) {
485 if (pInit->init_func)
486 (*pInit->init_func)();
488 if (! (alg = PAF_ALG_create(pInit->ialg_fxns,NULL,(IALG_Params *)pInit->ialg_prms,
489 common, pafConfig))) {
490 if (log) {
491 LOG_printf(log,
492 "AS%d: beta 0x%x algorithm instance creation failed",
493 stream, beta);
494 }
495 return NULL;
496 }
497 }
498 else
499 return NULL;
501 this->alg = (ASP_Handle )alg;
503 if (alg->fxns->algControl) {
504 if (! alg->fxns->algControl (alg, ACP_GETSTATUSADDRESS1, (IALG_Status *)&pStatus))
505 acp->fxns->attach (acp, pInit->thisCode.part.series, beta, pStatus);
506 if (! alg->fxns->algControl (alg, ACP_GETSTATUSADDRESS2, (IALG_Status *)&pStatus))
507 acp->fxns->attach (acp, pInit->thisCode.part.series, beta+1, pStatus);
508 }
510 if (log)
511 LOG_printf(log, "AS%d: beta 0x%x processing initialized", stream, beta);
513 return this;
514 }
516 //
517 // Audio Stream Processing Chain Function - Link Copy
518 //
519 // Name: PAF_ASP_linkCopy
520 // Purpose: Copy the data for a chain link:
521 // (1) Find an element on a chain, and
522 // (2) Copy the reference to the data of the link.
523 // From: AST Parameter Chain Function -> linkCopy
524 // Uses: See code.
525 // States: None.
526 // Return: Null pointer on failure.
527 // Pointer to the chain link on success.
528 // Trace: None.
529 //
531 PAF_ASP_Link *
532 PAF_ASP_linkCopy (
533 PAF_ASP_Link *this,
534 const PAF_ASP_LinkInit *pInit,
535 PAF_ASP_Link *from)
536 {
537 for ( ; from; from = from->next) {
538 if (from->code.full == pInit->thisCode.full)
539 break;
540 }
542 if (! from)
543 return NULL;
545 this->next = NULL;
546 this->code = pInit->thisCode;
547 this->alg = from->alg;
549 return this;
550 }
552 //
553 // Audio Stream Processing Chain Functions
554 //
555 // Name: PAF_ASP_chainFxns
556 // Purpose: Collect the chain functions that embody the implementation
557 // of Audio Framework Number 2 for use as a jump table.
558 // From: PAF_AST_Params
559 // Uses: See contents.
560 // States: N.A.
561 // Return: N.A.
562 // Trace: None.
563 //
565 const struct PAF_ASP_ChainFxns PAF_ASP_chainFxns =
566 {
567 PAF_ASP_chainInit_,
568 PAF_ASP_chainLink_,
569 PAF_ASP_chainFind_,
570 {
571 PAF_ASP_chainReset_,
572 PAF_ASP_chainApply_,
573 PAF_ASP_chainFinal_,
574 },
575 PAF_ASP_linkData,
576 PAF_ASP_linkCopy,
577 };