[processor-sdk/performance-audio-sr.git] / processor_audio_sdk_1_00_00_00 / pasdk / test_dsp / framework / aspDecOpCircBuf_master.c
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 #include <string.h> // for memset()
37 #include <xdc/std.h>
38 #include <ti/sysbios/hal/Cache.h>
39 #include <xdc/runtime/Log.h>
40 #include <ti/ipc/GateMP.h>
42 #include "common.h"
43 #include "paftyp.h"
44 #include "pafdec.h"
45 #include "aspDecOpCircBuf_master.h"
47 #define MAX_NUM_AF_PCM ( 4 )
48 #define CB_INIT_RD_LAG_PCM ( 2 ) // 0...3
50 #define MAX_NUM_AF_DDP ( 2 )
51 #define CB_INIT_RD_LAG_DDP ( 4 ) // 0...5
53 // Generate mute AF on circular buffer read
54 static Void cbReadAfMute(
55 PAF_AudioFrame *pAfRd, // audio frame into which to read
56 Int16 strFrameLen // stream frame length (output transaction size)
57 );
60 // Initialize circular buffer control
61 Int cbCtlInit(
62 PAF_AST_DecOpCircBufCtl *pCbCtl, // decoder output circular buffer control
63 PAF_AST_DecOpCircBuf *xDecOpCb // decoder output circular buffer base pointer
64 )
65 {
66 GateMP_Params gateParams;
67 GateMP_Handle gateHandle;
69 GateMP_Params_init(&gateParams);
70 gateParams.localProtect = GateMP_LocalProtect_THREAD;
71 gateParams.remoteProtect = GateMP_RemoteProtect_SYSTEM;
72 gateParams.name = ASP_DECODE_CB_GATE_NAME;
73 gateParams.regionId = ASP_DECODE_CB_GATE_REGION_ID;
74 gateHandle = GateMP_create(&gateParams);
75 if (gateHandle != NULL)
76 {
77 pCbCtl->gateHandle = gateHandle;
78 }
79 else
80 {
81 pCbCtl->gateHandle = NULL;
82 return ASP_DECOP_CB_CTL_INIT_INV_GATE;
83 }
85 pCbCtl->xDecOpCb = xDecOpCb;
87 return ASP_DECOP_CB_SOK;
89 }
91 // Initialize circular buffer
92 Int cbInit(
93 PAF_AST_DecOpCircBufCtl *pCbCtl, // decoder output circular buffer control
94 Int8 cbIdx, // decoder output circular buffer index
95 Int8 sourceSelect, // source select (PCM, DDP, etc.)
96 Int16 decOpFrameLen, // decoder output frame length (PCM samples)
97 Int16 strFrameLen, // stream frame length (PCM samples)
98 Int8 resetRwFlags // whether to reset reader, writer, and empty flags
99 )
100 {
101 IArg key;
102 GateMP_Handle gateHandle;
103 PAF_AST_DecOpCircBuf *pCb;
104 PAF_AudioFrame *pAfCb;
105 PAF_AudioData *pPcmBuf;
106 UInt8 *pMetaBuf; //QIN
107 Int8 n;
108 Int8 i;
110 // Get gate handle
111 gateHandle = pCbCtl->gateHandle;
112 // Enter gate
113 key = GateMP_enter(gateHandle);
115 // Get circular buffer base pointer
116 pCb = &pCbCtl->xDecOpCb[cbIdx];
118 // set input frame length
119 pCb->decOpFrameLen = decOpFrameLen;
121 // set output frame length
122 pCb->strFrameLen = strFrameLen;
124 // initialize circular buffer maximum number of audio frames
125 if (sourceSelect == PAF_SOURCE_PCM)
126 {
127 pCb->maxNumAfCb = MAX_NUM_AF_PCM;
128 pCb->afWrtIdx = CB_INIT_RD_LAG_PCM;
129 pCb->afRdIdx = 0;
130 pCb->pcmRdIdx = 0; // 2*256 in behind
132 // initialize audio frames
133 for (n=0; n<pCb->maxNumAfCb; n++)
134 {
135 pAfCb = &pCb->afCb[n];
136 pAfCb->sampleDecode = PAF_SOURCE_PCM;
137 PAF_PROCESS_ZERO(pAfCb->sampleProcess);
138 pAfCb->sampleRate = PAF_SAMPLERATE_48000HZ;
139 pAfCb->sampleCount = decOpFrameLen;
140 pAfCb->channelConfigurationRequest.full = 0;
141 pAfCb->channelConfigurationRequest.part.sat = PAF_CC_SAT_SURROUND4;
142 pAfCb->channelConfigurationRequest.part.sub = PAF_CC_SUB_ONE;
143 pAfCb->channelConfigurationStream.full = 0;
144 pAfCb->channelConfigurationStream.part.sat = PAF_CC_SAT_SURROUND4;
145 pAfCb->channelConfigurationStream.part.sub = PAF_CC_SUB_ONE;
146 }
147 }
148 else if (sourceSelect == PAF_SOURCE_DDP)
149 {
150 pCb->maxNumAfCb = MAX_NUM_AF_DDP;
151 pCb->afWrtIdx = 1;
152 pCb->afRdIdx = 0;
153 pCb->pcmRdIdx = decOpFrameLen - CB_INIT_RD_LAG_DDP*strFrameLen; // 4*256 behind
155 // initialize audio frames
156 for (n=0; n<pCb->maxNumAfCb; n++)
157 {
158 pAfCb = &pCb->afCb[n];
159 pAfCb->sampleDecode = PAF_SOURCE_DDP;
160 PAF_PROCESS_ZERO(pAfCb->sampleProcess);
161 pAfCb->sampleRate = PAF_SAMPLERATE_48000HZ;
162 pAfCb->sampleCount = decOpFrameLen;
163 pAfCb->channelConfigurationRequest.full = 0;
164 pAfCb->channelConfigurationRequest.part.sat = PAF_CC_SAT_SURROUND4;
165 pAfCb->channelConfigurationRequest.part.sub = PAF_CC_SUB_ONE;
166 pAfCb->channelConfigurationStream.full = 0;
167 pAfCb->channelConfigurationStream.part.sat = PAF_CC_SAT_SURROUND4;
168 pAfCb->channelConfigurationStream.part.sub = PAF_CC_SUB_ONE;
169 }
170 }
171 else
172 {
173 // Leave the gate
174 GateMP_leave(gateHandle, key);
176 return ASP_DECOP_CB_INIT_INV_SOURCE_SEL;
177 }
179 // initialize circular buffer current number of frames
180 pCb->numAfCb = pCb->afWrtIdx - pCb->afRdIdx;
182 // initialize audio frame PCM buffers
183 pPcmBuf = pCb->pcmBuf;
184 pMetaBuf = pCb->metaBuf; //QIN
185 for (n=0; n<pCb->maxNumAfCb; n++)
186 {
187 pAfCb = &pCb->afCb[n];
188 pAfCb->data.nChannels = ASP_DECOP_CB_MAX_NUM_PCM_CH;
189 pAfCb->data.nSamples = decOpFrameLen;
190 for (i=0; i<ASP_DECOP_CB_MAX_NUM_PCM_CH; i++)
191 {
192 pAfCb->data.sample[i] = pPcmBuf;
193 memset(pAfCb->data.sample[i], decOpFrameLen, 0);
194 pPcmBuf += decOpFrameLen;
196 pAfCb->data.samsiz[i] = 0;
197 }
199 // Initialize metadata buffers //QIN
200 for (i=0; i<PAF_MAX_NUM_PRIVATE_MD; i++)
201 {
202 pAfCb->pafPrivateMetadata[i].offset = 0;
203 pAfCb->pafPrivateMetadata[i].size = 0;
204 pAfCb->pafPrivateMetadata[i].pMdBuf = pMetaBuf;
205 pMetaBuf += PAF_MAX_PRIVATE_MD_SZ;
206 }
207 }
209 // reset read/write flags
210 if (resetRwFlags)
211 {
212 pCb->writerActiveFlag = 0;
213 pCb->readerActiveFlag = 0;
214 pCb->emptyFlag = 0;
215 }
216 // reset error counts
217 pCb->errUndCnt = 0;
218 pCb->errOvrCnt = 0;
220 // (***) FL: revisit
221 // Write back circular buffer configuration
222 Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
223 // Write back AF circular buffer
224 Cache_wb(pCb->afCb, pCb->maxNumAfCb*sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0);
225 // Write back PCM data
226 for (n=0; n<pCb->maxNumAfCb; n++)
227 {
228 pAfCb = &pCb->afCb[n];
229 Cache_wb(pAfCb->data.samsiz, ASP_DECOP_CB_MAX_NUM_PCM_CH*sizeof(PAF_AudioSize), Cache_Type_ALLD, 0);
230 Cache_wb(pAfCb->data.sample, ASP_DECOP_CB_MAX_NUM_PCM_CH*sizeof(PAF_AudioData *), Cache_Type_ALLD, 0);
231 for (i=0; i<ASP_DECOP_CB_MAX_NUM_PCM_CH; i++)
232 {
233 Cache_wb(pAfCb->data.sample[i], decOpFrameLen*sizeof(PAF_AudioData), Cache_Type_ALLD, 0);
234 }
235 // FL: unnecessary since part of AF
236 //for (i=0; i<PAF_MAX_NUM_PRIVATE_MD; i++) // Write back metadata //QIN
237 //{
238 // Cache_wb(&pAfCb->pafPrivateMetadata[i], sizeof(PAF_PrivateMetadata), Cache_Type_ALLD, 0);
239 //}
240 }
241 Cache_wait();
243 // Leave the gate
244 GateMP_leave(gateHandle, key);
246 return ASP_DECOP_CB_SOK;
247 }
249 // Start reads from circular buffer
250 Int cbReadStart(
251 PAF_AST_DecOpCircBufCtl *pCbCtl, // decoder output circular buffer control
252 Int8 cbIdx // decoder output circular buffer index
253 )
254 {
255 IArg key;
256 GateMP_Handle gateHandle;
257 PAF_AST_DecOpCircBuf *pCb;
259 // Get gate handle
260 gateHandle = pCbCtl->gateHandle;
261 // Enter gate
262 key = GateMP_enter(gateHandle);
264 // Get circular buffer base pointer
265 pCb = &pCbCtl->xDecOpCb[cbIdx];
267 // Invalidate circular buffer configuration
268 Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
269 Cache_wait();
271 // update flags
272 pCb->readerActiveFlag = 1;
274 // (***) FL: revisit
275 // Write back circular buffer configuration
276 Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
277 Cache_wait();
279 // Leave the gate
280 GateMP_leave(gateHandle, key);
282 return ASP_DECOP_CB_SOK;
283 }
285 // Stop reads from circular buffer
286 Int cbReadStop(
287 PAF_AST_DecOpCircBufCtl *pCbCtl, // decoder output circular buffer control
288 Int8 cbIdx // decoder output circular buffer index
289 )
290 {
291 IArg key;
292 GateMP_Handle gateHandle;
293 PAF_AST_DecOpCircBuf *pCb;
295 // Get gate handle
296 gateHandle = pCbCtl->gateHandle;
297 // Enter gate
298 key = GateMP_enter(gateHandle);
300 // Get circular buffer base pointer
301 pCb = &pCbCtl->xDecOpCb[cbIdx];
303 // Invalidate circular buffer configuration
304 Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
305 Cache_wait();
307 // update flags
308 pCb->readerActiveFlag = 0;
310 // (***) FL: revisit
311 // Write back circular buffer configuration
312 Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
313 Cache_wait();
315 // Leave the gate
316 GateMP_leave(gateHandle, key);
318 return ASP_DECOP_CB_SOK;
319 }
321 // Read audio frame from circular buffer
322 Int cbReadAf(
323 PAF_AST_DecOpCircBufCtl *pCbCtl, // decoder output circular buffer control
324 Int8 cbIdx, // decoder output circular buffer index
325 PAF_AudioFrame *pAfRd // audio frame into which to read
326 )
327 {
328 IArg key;
329 GateMP_Handle gateHandle;
330 PAF_AST_DecOpCircBuf *pCb;
331 PAF_AudioFrame *pAfCb;
332 PAF_ChannelMask_HD streamMask;
333 Int8 i;
334 Int16 j;
336 // Get gate handle
337 gateHandle = pCbCtl->gateHandle;
338 // Enter gate
339 key = GateMP_enter(gateHandle);
341 // Get circular buffer base pointer
342 pCb = &pCbCtl->xDecOpCb[cbIdx];
344 // (***) FL: revisit
345 // Invalidate circular buffer configuration.
346 Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
347 Cache_wait();
349 if ((pCb->writerActiveFlag == 1) && (pCb->emptyFlag == 1))
350 {
351 // This shouldn't occur:
352 // writer is active AND draining circular buffer
353 Log_info2("cbReadAf: ERROR: writerActiveFlag=%d, emptyFlag=%d", pCb->writerActiveFlag, pCb->emptyFlag);
354 SW_BREAKPOINT; // FL: debug
356 // Leave the gate
357 GateMP_leave(gateHandle, key);
359 return ASP_DECOP_CB_READ_INVSTATE;
360 }
362 if ((pCb->writerActiveFlag == 0) && (pCb->emptyFlag == 0))
363 {
364 //
365 // No active writer, not draining circular buffer.
366 // Skip UNDerflow check, mute output.
367 //
368 cbReadAfMute(pAfRd, pCb->strFrameLen);
370 // Leave the gate
371 GateMP_leave(gateHandle, key);
373 return ASP_DECOP_CB_SOK;
374 }
376 if ((pCb->writerActiveFlag == 1))
377 {
378 // check underflow
379 if (pCb->numAfCb <= 0)
380 {
381 //
382 // Increment underflow count.
383 // Mute output on underflow.
384 //
385 pCb->errUndCnt++;
386 cbReadAfMute(pAfRd, pCb->strFrameLen);
387 //SW_BREAKPOINT; // FL: debug
389 // Write back circular buffer configuration.
390 Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
391 Cache_wait();
393 // Leave the gate
394 GateMP_leave(gateHandle, key);
396 return ASP_DECOP_CB_READ_UNDERFLOW;
397 }
398 }
400 if ((pCb->writerActiveFlag == 1) || (pCb->emptyFlag == 1))
401 {
402 //
403 // Writer active or draining remaining frames in circular buffer.
404 // Get next output audio frame.
405 //
407 // get pointer to current audio frame in circular buffer
408 pAfCb = &pCb->afCb[pCb->afRdIdx];
410 // (***) FL: revisit
411 // Invalidate audio frame
412 Cache_inv(pAfCb, sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0);
413 Cache_inv(pAfCb->data.samsiz, ASP_DECOP_CB_MAX_NUM_PCM_CH*sizeof(PAF_AudioSize), Cache_Type_ALLD, 0);
414 for (i=0; i<pAfCb->numPrivateMetadata; i++) //QIN // FL: only invalidate numPrivateMetadata
415 {
416 //Cache_inv(&pAfCb->pafPrivateMetadata[i], sizeof(PAF_PrivateMetadata), Cache_Type_ALLD, 0); // FL: unnecessary since part of AF
417 Cache_inv(pAfCb->pafPrivateMetadata[i].pMdBuf, pAfCb->pafPrivateMetadata[i].size, Cache_Type_ALLD, 0); // FL: only update metadata package size
418 }
419 Cache_wait();
421 // compute stream mask
422 streamMask = pAfRd->fxns->channelMask(pAfRd, pAfCb->channelConfigurationStream);
424 // Invalidate PCM data
425 for (i = 0; i < ASP_DECOP_CB_MAX_NUM_PCM_CH; i++)
426 {
427 if ((streamMask >> i) & 0x1)
428 {
429 Cache_inv(&pAfCb->data.sample[i][pCb->pcmRdIdx], pCb->strFrameLen*sizeof(PAF_AudioData), Cache_Type_ALLD, 0);
430 }
431 }
432 Cache_wait();
434 // read audio frame information updated by decoder
435 pAfRd->sampleDecode = pAfCb->sampleDecode;
436 PAF_PROCESS_COPY(pAfRd->sampleProcess, pAfCb->sampleProcess);
437 pAfRd->sampleRate = pAfCb->sampleRate;
438 pAfRd->sampleCount = pCb->strFrameLen;
439 pAfRd->channelConfigurationRequest = pAfCb->channelConfigurationRequest;
440 pAfRd->channelConfigurationStream = pAfCb->channelConfigurationStream;
442 // read metadata information updated by decoder //QIN
443 pAfRd->bsMetadata_type = pAfCb->bsMetadata_type; /* non zero if metadata is attached. */
444 pAfRd->pafBsMetadataUpdate = pAfCb->pafBsMetadataUpdate; /* indicates whether bit-stream metadata update */
445 pAfRd->numPrivateMetadata = pAfCb->numPrivateMetadata; /* number of valid private metadata (0 or 1 if metadata filtering enabled) */
446 pAfRd->bsMetadata_offset = pAfCb->bsMetadata_offset; /* offset into audio frame for change in bsMetadata_type field */
448 // read PCM samples
449 for (i = 0; i < ASP_DECOP_CB_MAX_NUM_PCM_CH; i++)
450 {
451 if ((streamMask >> i) & 0x1)
452 {
453 for (j = 0; j < pCb->strFrameLen; j++)
454 {
455 pAfRd->data.sample[i][j] = pAfCb->data.sample[i][pCb->pcmRdIdx+j];
456 }
458 pAfRd->data.samsiz[i] = pAfCb->data.samsiz[i];
459 }
460 }
461 // read metadata //QIN
462 for (i = 0; i < pAfCb->numPrivateMetadata; i++) // FL: only read numPrivateMetadata
463 {
464 // FL: this is done above
465 ////Invalidate metadata data
466 //Cache_inv(&pAfCb->pafPrivateMetadata[i], sizeof(PAF_PrivateMetadata), Cache_Type_ALLD, 0);
467 //Cache_wait();
469 if ((pAfCb->pafPrivateMetadata[i].offset >= pCb->pcmRdIdx)
470 &&(pAfCb->pafPrivateMetadata[i].offset < (pCb->pcmRdIdx + pCb->strFrameLen))
471 &&(pAfCb->pafPrivateMetadata[i].size))
472 {
473 // FL: this is done above
474 ////Invalidate metadata data
475 //Cache_inv(pAfCb->pafPrivateMetadata[i].pMdBuf, pAfCb->pafPrivateMetadata[i].size, Cache_Type_ALLD, 0);
476 //Cache_wait();
478 // the offset is adjusted for segment [pCb->pcmRdIdx, (pCb->pcmRdIdx + pCb->pafFrameLen)]
479 pAfRd->pafPrivateMetadata[i].offset = 0; //pAfCb->pafPrivateMetadata[i].offset - pCb->pcmRdIdx;
480 pAfRd->pafPrivateMetadata[i].size = pAfCb->pafPrivateMetadata[i].size;
481 memcpy(pAfRd->pafPrivateMetadata[i].pMdBuf, pAfCb->pafPrivateMetadata[i].pMdBuf, pAfCb->pafPrivateMetadata[i].size);
482 }
483 else //reset un-used buf
484 {
485 pAfRd->pafPrivateMetadata[i].offset = 0;
486 pAfRd->pafPrivateMetadata[i].size = 0;
487 }
488 }
490 pCb->pcmRdIdx += pCb->strFrameLen; // update PCM read index
491 if (pCb->pcmRdIdx == pCb->decOpFrameLen)
492 {
493 // update audio frame read index
494 pCb->afRdIdx++;
495 if (pCb->afRdIdx >= pCb->maxNumAfCb)
496 {
497 pCb->afRdIdx = 0;
498 }
500 // update PCM read index
501 pCb->pcmRdIdx = 0;
503 // update number of audio frames in circular buffer
504 pCb->numAfCb--;
505 }
506 }
508 if (pCb->emptyFlag == 1)
509 {
510 //
511 // Writer inactive, but remaining frames in circular buffer.
512 // Update empty flag.
513 //
514 if (pCb->numAfCb <= 0)
515 {
516 pCb->emptyFlag = 0;
517 }
518 }
520 // (***) FL: revisit
521 // Write back circular buffer configuration.
522 // NOTE: Probably only a subset of this information needs to be updated.
523 Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
524 Cache_wait();
526 // Leave the gate
527 GateMP_leave(gateHandle, key);
529 return ASP_DECOP_CB_SOK;
530 }
532 // Generate mute AF on circular buffer read
533 static Void cbReadAfMute(
534 PAF_AudioFrame *pAfRd, // audio frame into which to read
535 Int16 strFrameLen // stream frame length (output transaction size)
536 )
537 {
538 PAF_ChannelMask_HD streamMask;
539 Int8 i;
541 pAfRd->sampleDecode = PAF_SOURCE_PCM;
542 PAF_PROCESS_ZERO(pAfRd->sampleProcess);
543 pAfRd->sampleRate = PAF_SAMPLERATE_48000HZ;
544 pAfRd->sampleCount = strFrameLen;
545 pAfRd->channelConfigurationRequest.full = 0;
546 pAfRd->channelConfigurationRequest.part.sat = PAF_CC_SAT_SURROUND4;
547 pAfRd->channelConfigurationRequest.part.sub = PAF_CC_SUB_ONE;
548 pAfRd->channelConfigurationStream.full = 0;
549 pAfRd->channelConfigurationStream.part.sat = PAF_CC_SAT_SURROUND4;
550 pAfRd->channelConfigurationStream.part.sub = PAF_CC_SUB_ONE;
552 // compute stream mask
553 streamMask = pAfRd->fxns->channelMask(pAfRd, pAfRd->channelConfigurationStream);
554 // Clear PCM data
555 for (i = 0; i < ASP_DECOP_CB_MAX_NUM_PCM_CH; i++)
556 {
557 if ((streamMask >> i) & 0x1)
558 {
559 memset(pAfRd->data.sample[i], strFrameLen, 0);
560 }
561 pAfRd->data.samsiz[i] = 0;
562 }
563 }