source: svn/newcon3bcm2_21bu/nexus/modules/audio/7552/src/nexus_audio_capture.c

Last change on this file was 76, checked in by megakiss, 10 years ago

1W 대기전력을 만족시키기 위하여 POWEROFF시 튜너를 Standby 상태로 함

  • Property svn:executable set to *
File size: 32.0 KB
Line 
1/***************************************************************************
2*     (c)2004-2011 Broadcom Corporation
3*
4*  This program is the proprietary software of Broadcom Corporation and/or its licensors,
5*  and may only be used, duplicated, modified or distributed pursuant to the terms and
6*  conditions of a separate, written license agreement executed between you and Broadcom
7*  (an "Authorized License").  Except as set forth in an Authorized License, Broadcom grants
8*  no license (express or implied), right to use, or waiver of any kind with respect to the
9*  Software, and Broadcom expressly reserves all rights in and to the Software and all
10*  intellectual property rights therein.  IF YOU HAVE NO AUTHORIZED LICENSE, THEN YOU
11*  HAVE NO RIGHT TO USE THIS SOFTWARE IN ANY WAY, AND SHOULD IMMEDIATELY
12*  NOTIFY BROADCOM AND DISCONTINUE ALL USE OF THE SOFTWARE.
13*
14*  Except as expressly set forth in the Authorized License,
15*
16*  1.     This program, including its structure, sequence and organization, constitutes the valuable trade
17*  secrets of Broadcom, and you shall use all reasonable efforts to protect the confidentiality thereof,
18*  and to use this information only in connection with your use of Broadcom integrated circuit products.
19*
20*  2.     TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
21*  AND WITH ALL FAULTS AND BROADCOM MAKES NO PROMISES, REPRESENTATIONS OR
22*  WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
23*  THE SOFTWARE.  BROADCOM SPECIFICALLY DISCLAIMS ANY AND ALL IMPLIED WARRANTIES
24*  OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE,
25*  LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION
26*  OR CORRESPONDENCE TO DESCRIPTION. YOU ASSUME THE ENTIRE RISK ARISING OUT OF
27*  USE OR PERFORMANCE OF THE SOFTWARE.
28*
29*  3.     TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL BROADCOM OR ITS
30*  LICENSORS BE LIABLE FOR (i) CONSEQUENTIAL, INCIDENTAL, SPECIAL, INDIRECT, OR
31*  EXEMPLARY DAMAGES WHATSOEVER ARISING OUT OF OR IN ANY WAY RELATING TO YOUR
32*  USE OF OR INABILITY TO USE THE SOFTWARE EVEN IF BROADCOM HAS BEEN ADVISED OF
33*  THE POSSIBILITY OF SUCH DAMAGES; OR (ii) ANY AMOUNT IN EXCESS OF THE AMOUNT
34*  ACTUALLY PAID FOR THE SOFTWARE ITSELF OR U.S. $1, WHICHEVER IS GREATER. THESE
35*  LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF ESSENTIAL PURPOSE OF
36*  ANY LIMITED REMEDY.
37*
38* $brcm_Workfile: nexus_audio_capture.c $
39* $brcm_Revision: 6 $
40* $brcm_Date: 10/14/11 4:13p $
41*
42* API Description:
43*   API name: AudioCapture
44*    Specific APIs related to PCM audio capture.  This supports capture
45*    of data into memory from a decoder or other source.
46*
47* Revision History:
48*
49* $brcm_Log: /nexus/modules/audio/7422/src/nexus_audio_capture.c $
50*
51* 6   10/14/11 4:13p jgarrett
52* SW7425-1447: Coverity CID 33804,33803,33802,33801,33800
53*
54* 5   7/19/11 6:03p jgarrett
55* SW7358-80: Resolving warnings if NEXUS_NUM_AUDIO_CAPTURES=0
56*
57* 4   5/25/11 5:16p jgarrett
58* SW7425-408: Adding BDBG_OBJECT to input/output types and MS11 features
59*
60* 3   5/23/11 6:49p jgarrett
61* SW7425-402: Adding multichannel capture support
62*
63* 2   2/22/11 5:44p jgarrett
64* SW7422-146: Implemented type renaming based on filter graph review
65*  comments
66*
67* 1   12/17/10 3:56p jgarrett
68* SW7422-146: Adding initial nexus on APE for 7422
69*
70***************************************************************************/
71
72#include "nexus_audio_module.h"
73#include "nexus_audio_capture.h"
74
75BDBG_MODULE(nexus_audio_capture);
76
77/***************************************************************************
78Summary:
79Get default settings for opening an audio capture channel
80***************************************************************************/
81void NEXUS_AudioCapture_GetDefaultOpenSettings(
82    NEXUS_AudioCaptureOpenSettings *pSettings      /* [out] default settings */
83    )
84{
85    BAPE_OutputCaptureOpenSettings piSettings;
86    BKNI_Memset(pSettings, 0, sizeof(*pSettings));
87    BAPE_OutputCapture_GetDefaultOpenSettings(&piSettings);
88    pSettings->fifoSize = piSettings.bufferSize;
89    pSettings->multichannelFormat = NEXUS_AudioMultichannelFormat_eStereo;
90}
91
92#if NEXUS_NUM_AUDIO_CAPTURES
93static void NEXUS_AudioCapture_P_ConvertStereo24(NEXUS_AudioCaptureHandle handle);
94static void NEXUS_AudioCapture_P_ConvertStereo16(NEXUS_AudioCaptureHandle handle);
95static void NEXUS_AudioCapture_P_ConvertMultichannel(NEXUS_AudioCaptureHandle handle);
96static void NEXUS_AudioCapture_P_ConvertMono(NEXUS_AudioCaptureHandle handle, bool rightChannel);
97static void NEXUS_AudioCapture_P_ConvertMonoMix(NEXUS_AudioCaptureHandle handle);
98static void NEXUS_AudioCapture_P_Interrupt_isr(void *pParam, int param);
99static void NEXUS_AudioCapture_P_FlushDeviceBuffer_isr(NEXUS_AudioCaptureHandle handle);
100
101BDBG_OBJECT_ID(NEXUS_AudioCapture);
102
103typedef struct NEXUS_AudioCapture
104{
105    BDBG_OBJECT(NEXUS_AudioCapture)
106    bool opened;
107    bool running;
108    NEXUS_AudioMultichannelFormat multichannelFormat;
109    BAPE_OutputCaptureHandle apeHandle;
110    NEXUS_AudioOutputObject connector;
111    NEXUS_AudioCaptureSettings settings;
112    void *pMemory, *pCachedMemory;
113    uint32_t *pBuffer;
114    int bufferSize, rptr, wptr, bufferDepth;
115    NEXUS_IsrCallbackHandle callback;
116} NEXUS_AudioCapture;
117
118static NEXUS_AudioCapture g_captures[NEXUS_NUM_AUDIO_CAPTURES];
119
120NEXUS_AudioCaptureHandle NEXUS_AudioCapture_Open(     /* attr{destructor=NEXUS_AudioCapture_Close}  */
121    unsigned index,
122    const NEXUS_AudioCaptureOpenSettings *pSettings    /* Pass NULL for default settings */
123    )
124{
125    NEXUS_AudioCaptureOpenSettings defaults;
126    BAPE_OutputCaptureOpenSettings openSettings;
127    NEXUS_AudioCaptureHandle handle;
128    BAPE_OutputCaptureInterruptHandlers interrupts;
129    BAPE_OutputPort connector;
130    BERR_Code errCode;
131
132    if ( index >= NEXUS_NUM_AUDIO_CAPTURES )
133    {
134        BDBG_ERR(("index out of range."));
135        (void)BERR_TRACE(BERR_INVALID_PARAMETER);
136        return NULL;
137    }
138
139    handle = &g_captures[index];
140    if ( handle->opened )
141    {
142        BDBG_ERR(("AudioCapture %u already open", index));
143        (void)BERR_TRACE(BERR_NOT_SUPPORTED);
144        return NULL;
145    }
146
147    if ( NULL == pSettings )
148    {
149        NEXUS_AudioCapture_GetDefaultOpenSettings(&defaults);
150        pSettings = &defaults;
151    }
152
153    BAPE_OutputCapture_GetDefaultOpenSettings(&openSettings);
154    switch ( pSettings->multichannelFormat )
155    {
156    case NEXUS_AudioMultichannelFormat_eStereo:
157        openSettings.numBuffers = 1;
158        openSettings.bufferSize = pSettings->fifoSize;
159        break;
160    case NEXUS_AudioMultichannelFormat_e5_1:
161        openSettings.numBuffers = 3;
162        openSettings.bufferSize = pSettings->fifoSize/3;
163        break;
164    default:
165        BDBG_ERR(("Unsupported multichannel format %u", pSettings->multichannelFormat));
166        (void)BERR_TRACE(BERR_INVALID_PARAMETER);
167        return NULL;
168    }
169    if ( pSettings->threshold )
170    {
171        openSettings.watermarkThreshold = pSettings->threshold & (~255);
172    }
173
174    handle->callback = NEXUS_IsrCallback_Create(handle, NULL);
175    if ( NULL == handle->callback )
176    {
177        (void)BERR_TRACE(BERR_OS_ERROR);
178        return NULL;
179    }
180
181    errCode = BAPE_OutputCapture_Open(NEXUS_AUDIO_DEVICE_HANDLE, index, &openSettings, &handle->apeHandle);
182    if ( errCode )
183    {
184        (void)BERR_TRACE(errCode);
185        NEXUS_IsrCallback_Destroy(handle->callback);
186        return NULL;
187    }
188
189    handle->pMemory = BMEM_Heap_Alloc(g_pCoreHandles->heap[0], pSettings->fifoSize);
190    if ( NULL == handle->pMemory )
191    {
192        (void)BERR_TRACE(BERR_OUT_OF_DEVICE_MEMORY);
193        BAPE_OutputCapture_Close(handle->apeHandle);
194        NEXUS_IsrCallback_Destroy(handle->callback);
195        return NULL;
196    }
197
198    errCode = BMEM_Heap_ConvertAddressToCached(g_pCoreHandles->heap[0], handle->pMemory, &handle->pCachedMemory);
199    if ( errCode )
200    {
201        (void)BERR_TRACE(errCode);
202        BMEM_Heap_Free(g_pCoreHandles->heap[0], handle->pMemory);
203        BAPE_OutputCapture_Close(handle->apeHandle);
204        NEXUS_IsrCallback_Destroy(handle->callback);
205        return NULL;       
206    }
207
208    handle->pBuffer = handle->pCachedMemory;
209    handle->bufferSize = pSettings->fifoSize;
210
211    BDBG_OBJECT_SET(handle, NEXUS_AudioCapture);
212    handle->opened = true;
213    NEXUS_AUDIO_OUTPUT_INIT(&handle->connector, NEXUS_AudioOutputType_eCapture, handle);
214    BAPE_OutputCapture_GetOutputPort(handle->apeHandle, &connector);
215    handle->connector.port = (uint32_t)connector;
216    handle->settings.format = NEXUS_AudioCaptureFormat_e16BitStereo;
217
218    BAPE_OutputCapture_GetInterruptHandlers(handle->apeHandle, &interrupts);
219    interrupts.watermark.pCallback_isr = NEXUS_AudioCapture_P_Interrupt_isr;
220    interrupts.watermark.pParam1 = handle;
221    errCode = BAPE_OutputCapture_SetInterruptHandlers(handle->apeHandle, &interrupts);
222    BDBG_ASSERT(errCode == BERR_SUCCESS);
223
224    return handle;
225}
226
227void NEXUS_AudioCapture_Close(
228    NEXUS_AudioCaptureHandle handle
229    )
230{
231    BDBG_OBJECT_ASSERT(handle, NEXUS_AudioCapture);
232    BDBG_ASSERT(handle->opened);
233    NEXUS_AudioOutput_RemoveAllInputs(&handle->connector);
234    NEXUS_AudioOutput_Shutdown(&handle->connector);
235    BAPE_OutputCapture_Close(handle->apeHandle);
236    BMEM_Free(g_pCoreHandles->heap[0], handle->pMemory);
237    BKNI_Memset(handle, 0, sizeof(NEXUS_AudioCapture));
238}
239
240void NEXUS_AudioCapture_GetSettings(
241    NEXUS_AudioCaptureHandle handle,
242    NEXUS_AudioCaptureSettings *pSettings /* [out] */
243    )
244{
245    BDBG_OBJECT_ASSERT(handle, NEXUS_AudioCapture);
246    BDBG_ASSERT(handle->opened);
247    BDBG_ASSERT(NULL != pSettings);
248    *pSettings = handle->settings;
249}
250
251NEXUS_Error NEXUS_AudioCapture_SetSettings(
252    NEXUS_AudioCaptureHandle handle,
253    const NEXUS_AudioCaptureSettings *pSettings
254    )
255{
256    BDBG_OBJECT_ASSERT(handle, NEXUS_AudioCapture);
257    BDBG_ASSERT(handle->opened);
258    BDBG_ASSERT(NULL != pSettings);
259    handle->settings = *pSettings;
260    return BERR_SUCCESS;
261}
262
263void NEXUS_AudioCapture_GetDefaultStartSettings(
264    NEXUS_AudioCaptureStartSettings *pSettings  /* [out] default settings */
265    )
266{
267    BDBG_ASSERT(NULL != pSettings);
268    BKNI_Memset(pSettings, 0, sizeof(*pSettings));
269}
270
271NEXUS_Error NEXUS_AudioCapture_Start(
272    NEXUS_AudioCaptureHandle handle,
273    const NEXUS_AudioCaptureStartSettings *pSettings
274    )
275{
276    BDBG_OBJECT_ASSERT(handle, NEXUS_AudioCapture);
277
278    if ( handle->running )
279    {
280        BDBG_ERR(("Already running"));
281        return BERR_TRACE(BERR_INVALID_PARAMETER);
282    }
283
284    /* Setup callback */
285    NEXUS_IsrCallback_Set(handle->callback, pSettings?&pSettings->dataCallback:NULL);
286
287    /* Setup internal buffer and start */
288    BKNI_EnterCriticalSection();
289    NEXUS_AudioCapture_P_FlushDeviceBuffer_isr(handle);
290    handle->running = true;
291    handle->wptr = handle->rptr = handle->bufferDepth = 0;
292    BKNI_LeaveCriticalSection();
293
294    return BERR_SUCCESS;
295}
296
297void NEXUS_AudioCapture_Stop(
298    NEXUS_AudioCaptureHandle handle
299    )
300{
301    BDBG_OBJECT_ASSERT(handle, NEXUS_AudioCapture);
302
303    BDBG_MSG(("Stopping"));
304
305    BKNI_EnterCriticalSection();
306    handle->running = false;
307    BKNI_LeaveCriticalSection();
308}
309
310NEXUS_Error NEXUS_AudioCapture_GetBuffer(
311    NEXUS_AudioCaptureHandle handle,
312    void **ppBuffer,    /* [out] attr{memory=cached} pointer to memory mapped
313                                 region that contains captured data. */
314    size_t *pSize       /* [out] total number of readable, contiguous bytes which the buffers are pointing to */
315    )
316{
317    BDBG_OBJECT_ASSERT(handle, NEXUS_AudioCapture);
318    BDBG_ASSERT(NULL != ppBuffer);
319    BDBG_ASSERT(NULL != pSize);
320
321    /* Defaults for error returns */
322    *ppBuffer = NULL;
323    *pSize = 0;
324
325    if ( !handle->running )
326    {
327        return BERR_TRACE(BERR_INVALID_PARAMETER);
328    }
329
330    BDBG_MSG(("Before Conversion rptr %d wptr %d depth %d/%d", handle->rptr, handle->wptr, handle->bufferDepth, handle->bufferSize));
331
332    switch ( handle->settings.format )
333    {
334    case NEXUS_AudioCaptureFormat_e24BitStereo:
335        NEXUS_AudioCapture_P_ConvertStereo24(handle);
336        break;
337    case NEXUS_AudioCaptureFormat_e16BitStereo:
338        NEXUS_AudioCapture_P_ConvertStereo16(handle);
339        break;
340    case NEXUS_AudioCaptureFormat_e16BitMonoLeft:
341        NEXUS_AudioCapture_P_ConvertMono(handle, false);
342        break;
343    case NEXUS_AudioCaptureFormat_e16BitMonoRight:
344        NEXUS_AudioCapture_P_ConvertMono(handle, true);
345        break;
346    case NEXUS_AudioCaptureFormat_e16BitMono:
347        NEXUS_AudioCapture_P_ConvertMonoMix(handle);
348        break;
349    case NEXUS_AudioCaptureFormat_e24Bit5_1:
350        NEXUS_AudioCapture_P_ConvertMultichannel(handle);
351        break;
352    default:
353        return BERR_TRACE(BERR_NOT_SUPPORTED);
354    }
355
356    *ppBuffer = &handle->pBuffer[handle->rptr];
357    if ( handle->bufferDepth == 0 )
358    {
359        /* No data */
360        *pSize = 0;
361    }
362    else if ( handle->rptr < handle->wptr )
363    {
364        /* no wraparound */
365        *pSize = (handle->wptr - handle->rptr)*4;
366    }
367    else
368    {
369        /* Buffer has wrapped, give contiguous size to end of buffer */
370        *pSize = handle->bufferSize - (4*handle->rptr);
371    }
372
373    BDBG_MSG(("rptr %d wptr %d size %d words (%d bytes)", handle->rptr, handle->wptr, (*pSize)/4, *pSize));
374
375    return BERR_SUCCESS;
376}
377
378NEXUS_Error NEXUS_AudioCapture_WriteComplete(
379    NEXUS_AudioCaptureHandle handle,
380    size_t amountWritten            /* The number of bytes read from the buffer */
381    )
382{
383    int newRptr;
384
385    BDBG_OBJECT_ASSERT(handle, NEXUS_AudioCapture);
386
387    if ( !handle->running || NULL == handle )
388    {
389        return BERR_TRACE(BERR_INVALID_PARAMETER);
390    }
391
392    if ( amountWritten % 4 )
393    {
394        BDBG_ERR(("The buffer must be updated in increments of four bytes"));
395        return BERR_TRACE(BERR_INVALID_PARAMETER);
396    }
397
398    newRptr = handle->rptr + (amountWritten/4);
399
400    if ( newRptr == (handle->bufferSize/4) )
401    {
402        newRptr = 0;
403    }
404    else if ( newRptr > (handle->bufferSize/4) )
405    {
406        BDBG_ERR(("Overflow - invalid number of bytes passed"));
407        return BERR_TRACE(BERR_INVALID_PARAMETER);
408    }
409
410    /* Sanity check error cases where the read pointer passes the write pointer */
411    if ( newRptr != handle->wptr )
412    {
413        if ( (handle->rptr < handle->wptr) &&
414             (newRptr > handle->wptr) )
415        {
416            BDBG_ERR(("Overflow - invalid number of bytes passed"));
417            return BERR_TRACE(BERR_INVALID_PARAMETER);
418        }
419        else if ( (handle->rptr > handle->wptr) &&
420                  (newRptr < handle->wptr) &&
421                  newRptr != 0 )
422        {
423            BDBG_ERR(("Overflow - invalid number of bytes passed"));
424            return BERR_TRACE(BERR_INVALID_PARAMETER);
425        }
426    }
427
428    BDBG_MSG(("Write Complete - %d bytes written, moving rptr from %d to %d (size %d)", amountWritten, handle->rptr, newRptr, handle->bufferSize/4));
429
430    /* Update read pointer of our buffer */
431    handle->rptr = newRptr;
432    handle->bufferDepth -= amountWritten;
433
434    return BERR_SUCCESS;
435}
436
437NEXUS_AudioOutput NEXUS_AudioCapture_GetConnector( /* attr{shutdown=NEXUS_AudioOutput_Shutdown} */
438    NEXUS_AudioCaptureHandle handle
439    )
440{
441    BDBG_OBJECT_ASSERT(handle, NEXUS_AudioCapture);
442    return &handle->connector;
443}
444
445static size_t NEXUS_AudioCapture_P_GetContiguousSpace(NEXUS_AudioCaptureHandle handle)
446{
447    if ( handle->bufferDepth == handle->bufferSize )
448    {
449        return 0;
450    }
451    else if ( handle->wptr < handle->rptr )
452    {
453        /* No Wrap */
454        return handle->bufferSize - handle->bufferDepth;
455    }
456    else
457    {
458        /* Wrap - return contiguous amount */
459        return handle->bufferSize - (handle->wptr*4);
460    }
461}
462
463static void NEXUS_AudioCapture_P_AdvanceBuffer(NEXUS_AudioCaptureHandle handle, size_t bytes)
464{
465    handle->bufferDepth += bytes;
466    handle->wptr += (bytes)/4;
467    if ( handle->wptr >= (handle->bufferSize/4) )
468    {
469        handle->wptr = 0;
470    }
471}
472
473static void NEXUS_AudioCapture_P_ConvertStereo24(NEXUS_AudioCaptureHandle handle)
474{
475    BERR_Code errCode;
476    void *pCachedBuffer;
477    uint32_t *pSource;
478    size_t bufferSize, copied;
479    BAPE_BufferDescriptor bufferDescriptor;
480
481    for ( ;; )
482    {
483        errCode = BAPE_OutputCapture_GetBuffer(handle->apeHandle, &bufferDescriptor);
484        if ( errCode )
485        {
486            (void)BERR_TRACE(errCode);
487            return;
488        }
489        bufferSize = bufferDescriptor.bufferSize;
490        if ( bufferSize == 0 )
491        {
492            /* Done */
493            return;
494        }
495        errCode = BMEM_Heap_ConvertAddressToCached(g_pCoreHandles->heap[0], bufferDescriptor.buffers[BAPE_Channel_eLeft].pBuffer, &pCachedBuffer);
496        BDBG_ASSERT(errCode == BERR_SUCCESS);
497        pSource = pCachedBuffer;
498        copied = 0;
499        while ( bufferSize >= 4 )
500        {
501            size_t available, bytesToCopy;
502            if ( handle->bufferDepth > (handle->bufferSize-3) )
503            {
504                /* Our buffer is full. */
505                break;
506            }
507            available = NEXUS_AudioCapture_P_GetContiguousSpace(handle);
508            if ( available >= bufferSize )
509            {
510                bytesToCopy = bufferSize;
511            }
512            else
513            {
514                bytesToCopy = available;
515            }
516            while ( bytesToCopy > 0 )
517            {
518                handle->pBuffer[handle->wptr] = (*pSource++) & 0xffffff00;
519                NEXUS_AudioCapture_P_AdvanceBuffer(handle, 4);
520                copied += 4;
521                bufferSize -= 4;
522                bytesToCopy -= 4;
523            }
524        }
525        if ( copied == 0 )
526        {
527            return;
528        }
529        BMEM_Heap_FlushCache(g_pCoreHandles->heap[0], pCachedBuffer, copied);
530        errCode = BAPE_OutputCapture_ConsumeData(handle->apeHandle, copied);
531        if ( errCode )
532        {
533            (void)BERR_TRACE(errCode);
534            return;
535        }
536    }
537}
538
539static void NEXUS_AudioCapture_P_ConvertStereo16(NEXUS_AudioCaptureHandle handle)
540{
541    BERR_Code errCode;
542    void *pCachedBuffer;
543    uint32_t *pSource;
544    size_t bufferSize, copied;
545    BAPE_BufferDescriptor bufferDescriptor;
546
547    for ( ;; )
548    {
549        errCode = BAPE_OutputCapture_GetBuffer(handle->apeHandle, &bufferDescriptor);
550        if ( errCode )
551        {
552            (void)BERR_TRACE(errCode);
553            return;
554        }
555        bufferSize = bufferDescriptor.bufferSize;
556        if ( bufferSize == 0 )
557        {
558            /* Done */
559            return;
560        }
561        errCode = BMEM_Heap_ConvertAddressToCached(g_pCoreHandles->heap[0], bufferDescriptor.buffers[BAPE_Channel_eLeft].pBuffer, &pCachedBuffer);
562        BDBG_ASSERT(errCode == BERR_SUCCESS);
563        pSource = pCachedBuffer;
564        copied = 0;
565        while ( bufferSize >= 8 )
566        {
567            size_t available, bytesToCopy;
568            if ( handle->bufferDepth > (handle->bufferSize-3) )
569            {
570                /* Our buffer is full. */
571                break;
572            }
573            available = NEXUS_AudioCapture_P_GetContiguousSpace(handle);
574            if ( available >= bufferSize/2 )
575            {
576                bytesToCopy = bufferSize/2;
577            }
578            else
579            {
580                bytesToCopy = available;
581            }
582            while ( bytesToCopy > 0 )
583            {
584                uint32_t sample;
585                sample = (*pSource++)>>16;          /* Left */
586                sample |= (*pSource++)&0xffff0000;  /* Right */
587                handle->pBuffer[handle->wptr] = sample;
588                NEXUS_AudioCapture_P_AdvanceBuffer(handle, 4);
589                copied += 8;
590                bufferSize -= 8;
591                bytesToCopy -= 4;
592            }
593        }
594        if ( copied == 0 )
595        {
596            return;
597        }
598        BMEM_Heap_FlushCache(g_pCoreHandles->heap[0], pCachedBuffer, copied);
599        errCode = BAPE_OutputCapture_ConsumeData(handle->apeHandle, copied);
600        if ( errCode )
601        {
602            (void)BERR_TRACE(errCode);
603            return;
604        }
605    }
606}
607
608static void NEXUS_AudioCapture_P_Interrupt_isr(void *pParam, int param)
609{
610    NEXUS_AudioCaptureHandle handle;
611
612    handle = pParam;
613    BDBG_OBJECT_ASSERT(handle, NEXUS_AudioCapture);
614    BSTD_UNUSED(param);
615
616    BDBG_MSG(("Capture Interrupt"));
617
618    if ( handle->running )
619    {
620        /* Propagate directly to app.  They will read the data out as part of GetBuffer */
621        NEXUS_IsrCallback_Fire_isr(handle->callback);
622    }
623    else
624    {
625        NEXUS_AudioCapture_P_FlushDeviceBuffer_isr(handle);
626    }   
627}
628
629static void NEXUS_AudioCapture_P_FlushDeviceBuffer_isr(NEXUS_AudioCaptureHandle handle)
630{
631    BAPE_OutputCapture_Flush_isr(handle->apeHandle);
632}
633
634static void NEXUS_AudioCapture_P_ConvertMultichannel(NEXUS_AudioCaptureHandle handle)
635{
636    BERR_Code errCode;
637    void *pCachedBuffers[3] = {NULL, NULL, NULL};
638    uint32_t *pSource0, *pSource1, *pSource2;
639    size_t bufferSize, copied;
640    BAPE_BufferDescriptor bufferDescriptor;
641
642    for ( ;; )
643    {
644        errCode = BAPE_OutputCapture_GetBuffer(handle->apeHandle, &bufferDescriptor);
645        if ( errCode )
646        {
647            (void)BERR_TRACE(errCode);
648            return;
649        }
650        bufferSize = bufferDescriptor.bufferSize;
651        if ( bufferSize == 0 )
652        {
653            /* Done */
654            return;
655        }
656        if ( bufferDescriptor.buffers[BAPE_Channel_eLeft].pBuffer )
657        {
658            errCode = BMEM_Heap_ConvertAddressToCached(g_pCoreHandles->heap[0], bufferDescriptor.buffers[BAPE_Channel_eLeft].pBuffer, &pCachedBuffers[0]);
659            BDBG_ASSERT(errCode == BERR_SUCCESS);
660        }
661        if ( bufferDescriptor.buffers[BAPE_Channel_eLeftSurround].pBuffer )
662        {
663            errCode = BMEM_Heap_ConvertAddressToCached(g_pCoreHandles->heap[0], bufferDescriptor.buffers[BAPE_Channel_eLeftSurround].pBuffer, &pCachedBuffers[1]);
664            BDBG_ASSERT(errCode == BERR_SUCCESS);
665        }
666        if ( bufferDescriptor.buffers[BAPE_Channel_eCenter].pBuffer )
667        {
668            errCode = BMEM_Heap_ConvertAddressToCached(g_pCoreHandles->heap[0], bufferDescriptor.buffers[BAPE_Channel_eCenter].pBuffer, &pCachedBuffers[2]);
669            BDBG_ASSERT(errCode == BERR_SUCCESS);
670        }
671        pSource0 = pCachedBuffers[0];
672        pSource1 = pCachedBuffers[1];
673        pSource2 = pCachedBuffers[2];
674        copied = 0;
675        while ( bufferSize >= 8 )
676        {
677            size_t available, bytesToCopy;
678            if ( handle->bufferDepth > (handle->bufferSize-3) )
679            {
680                /* Our buffer is full. */
681                break;
682            }
683            available = NEXUS_AudioCapture_P_GetContiguousSpace(handle);
684            if ( available >= bufferSize*3 )
685            {
686                bytesToCopy = bufferSize*3;
687            }
688            else
689            {
690                bytesToCopy = available;
691            }
692            while ( bytesToCopy >= 24 )
693            {
694                handle->pBuffer[handle->wptr] = (*pSource0++) & 0xffffff00;
695                NEXUS_AudioCapture_P_AdvanceBuffer(handle, 4);
696                handle->pBuffer[handle->wptr] = (*pSource0++) & 0xffffff00;
697                NEXUS_AudioCapture_P_AdvanceBuffer(handle, 4);
698                if ( pSource1 )
699                {
700                    handle->pBuffer[handle->wptr] = (*pSource1++) & 0xffffff00;
701                    NEXUS_AudioCapture_P_AdvanceBuffer(handle, 4);
702                    handle->pBuffer[handle->wptr] = (*pSource1++) & 0xffffff00;
703                    NEXUS_AudioCapture_P_AdvanceBuffer(handle, 4);
704                }
705                else
706                {
707                    handle->pBuffer[handle->wptr] = 0;
708                    NEXUS_AudioCapture_P_AdvanceBuffer(handle, 4);
709                    handle->pBuffer[handle->wptr] = 0;
710                    NEXUS_AudioCapture_P_AdvanceBuffer(handle, 4);
711                }
712                if ( pSource2 )
713                {
714                    handle->pBuffer[handle->wptr] = (*pSource2++) & 0xffffff00;
715                    NEXUS_AudioCapture_P_AdvanceBuffer(handle, 4);
716                    handle->pBuffer[handle->wptr] = (*pSource2++) & 0xffffff00;
717                    NEXUS_AudioCapture_P_AdvanceBuffer(handle, 4);
718                }
719                else
720                {
721                    handle->pBuffer[handle->wptr] = 0;
722                    NEXUS_AudioCapture_P_AdvanceBuffer(handle, 4);
723                    handle->pBuffer[handle->wptr] = 0;
724                    NEXUS_AudioCapture_P_AdvanceBuffer(handle, 4);
725                }
726                bytesToCopy -= 24;
727                copied += 8;
728                bufferSize -= 8;
729            }
730        }
731        if ( copied == 0 )
732        {
733            return;
734        }
735        BMEM_Heap_FlushCache(g_pCoreHandles->heap[0], pCachedBuffers[0], copied);
736        if ( pCachedBuffers[1] )
737        {
738            BMEM_Heap_FlushCache(g_pCoreHandles->heap[0], pCachedBuffers[1], copied);
739        }
740        if ( pCachedBuffers[2] )
741        {
742            BMEM_Heap_FlushCache(g_pCoreHandles->heap[0], pCachedBuffers[2], copied);
743        }
744        errCode = BAPE_OutputCapture_ConsumeData(handle->apeHandle, copied);
745        if ( errCode )
746        {
747            (void)BERR_TRACE(errCode);
748            return;
749        }
750    }   
751}
752
753static void NEXUS_AudioCapture_P_ConvertMono(NEXUS_AudioCaptureHandle handle, bool rightChannel)
754{
755    BERR_Code errCode;
756    void *pCachedBuffer;
757    uint32_t *pSource;
758    size_t bufferSize, copied;
759    BAPE_BufferDescriptor bufferDescriptor;
760
761    for ( ;; )
762    {
763        errCode = BAPE_OutputCapture_GetBuffer(handle->apeHandle, &bufferDescriptor);
764        if ( errCode )
765        {
766            (void)BERR_TRACE(errCode);
767            return;
768        }
769        bufferSize = bufferDescriptor.bufferSize;
770        if ( bufferSize == 0 )
771        {
772            /* Done */
773            return;
774        }
775        errCode = BMEM_Heap_ConvertAddressToCached(g_pCoreHandles->heap[0], bufferDescriptor.buffers[BAPE_Channel_eLeft].pBuffer, &pCachedBuffer);
776        BDBG_ASSERT(errCode == BERR_SUCCESS);
777        pSource = pCachedBuffer;
778        copied = 0;
779        while ( bufferSize >= 16 )
780        {
781            size_t available, bytesToCopy;
782            if ( handle->bufferDepth > (handle->bufferSize-3) )
783            {
784                /* Our buffer is full. */
785                break;
786            }
787            available = NEXUS_AudioCapture_P_GetContiguousSpace(handle);
788            if ( available >= bufferSize/4 )
789            {
790                bytesToCopy = bufferSize/4;
791            }
792            else
793            {
794                bytesToCopy = available;
795            }
796            while ( bytesToCopy > 0 )
797            {
798                uint32_t sample;
799                if ( rightChannel )
800                {
801                    pSource++;                          /* Skip Left1 */
802                    sample = (*pSource++)&0xffff0000;   /* Right1 */
803                    pSource++;                          /* Skip Left2 */
804                    sample |= (*pSource++)>>16;         /* Right2 */
805                }
806                else
807                {
808                    sample = (*pSource++)&0xffff0000;   /* Left1 */
809                    pSource++;                          /* Skip Right1 */
810                    sample |= (*pSource++)>>16;         /* Left2 */
811                    pSource++;                          /* Skip Right2 */
812                }
813                handle->pBuffer[handle->wptr] = sample;
814                NEXUS_AudioCapture_P_AdvanceBuffer(handle, 4);
815                copied += 16;
816                bufferSize -= 16;
817                bytesToCopy -= 4;
818            }
819        }
820        if ( copied == 0 )
821        {
822            return;
823        }
824        BMEM_Heap_FlushCache(g_pCoreHandles->heap[0], pCachedBuffer, copied);
825        errCode = BAPE_OutputCapture_ConsumeData(handle->apeHandle, copied);
826        if ( errCode )
827        {
828            (void)BERR_TRACE(errCode);
829            return;
830        }
831    }
832}
833
834static void NEXUS_AudioCapture_P_ConvertMonoMix(NEXUS_AudioCaptureHandle handle)
835{
836    BERR_Code errCode;
837    void *pCachedBuffer;
838    uint32_t *pSource;
839    size_t bufferSize, copied;
840    BAPE_BufferDescriptor bufferDescriptor;
841
842    for ( ;; )
843    {
844        errCode = BAPE_OutputCapture_GetBuffer(handle->apeHandle, &bufferDescriptor);
845        if ( errCode )
846        {
847            (void)BERR_TRACE(errCode);
848            return;
849        }
850        bufferSize = bufferDescriptor.bufferSize;
851        if ( bufferSize == 0 )
852        {
853            /* Done */
854            return;
855        }
856        errCode = BMEM_Heap_ConvertAddressToCached(g_pCoreHandles->heap[0], bufferDescriptor.buffers[BAPE_Channel_eLeft].pBuffer, &pCachedBuffer);
857        BDBG_ASSERT(errCode == BERR_SUCCESS);
858        pSource = pCachedBuffer;
859        copied = 0;
860        while ( bufferSize >= 16 )
861        {
862            size_t available, bytesToCopy;
863            if ( handle->bufferDepth > (handle->bufferSize-3) )
864            {
865                /* Our buffer is full. */
866                break;
867            }
868            available = NEXUS_AudioCapture_P_GetContiguousSpace(handle);
869            if ( available >= bufferSize/4 )
870            {
871                bytesToCopy = bufferSize/4;
872            }
873            else
874            {
875                bytesToCopy = available;
876            }
877            while ( bytesToCopy > 0 )
878            {
879                uint32_t sample1, sample2;
880                sample1 = (*pSource++)>>16;
881                sample1 += (*pSource++)>>16;
882                sample1 /= 2;
883                sample2 = (*pSource++)>>16;
884                sample2 += (*pSource++)>>16;
885                sample2 /= 2;
886                handle->pBuffer[handle->wptr] = (sample1<<16)|sample2;
887                NEXUS_AudioCapture_P_AdvanceBuffer(handle, 4);
888                copied += 16;
889                bufferSize -= 16;
890                bytesToCopy -= 4;
891            }
892        }
893        if ( copied == 0 )
894        {
895            return;
896        }
897        BMEM_Heap_FlushCache(g_pCoreHandles->heap[0], pCachedBuffer, copied);
898        errCode = BAPE_OutputCapture_ConsumeData(handle->apeHandle, copied);
899        if ( errCode )
900        {
901            (void)BERR_TRACE(errCode);
902            return;
903        }
904    }
905}
906
907#else
908NEXUS_AudioCaptureHandle NEXUS_AudioCapture_Open(     /* attr{destructor=NEXUS_AudioCapture_Close}  */
909    unsigned index,
910    const NEXUS_AudioCaptureOpenSettings *pSettings    /* Pass NULL for default settings */
911    )
912{
913    BSTD_UNUSED(index);
914    BSTD_UNUSED(pSettings);
915    (void)BERR_TRACE(BERR_NOT_SUPPORTED);
916    return NULL;
917}
918
919void NEXUS_AudioCapture_Close(
920    NEXUS_AudioCaptureHandle handle
921    )
922{
923    BSTD_UNUSED(handle);
924}
925
926void NEXUS_AudioCapture_GetSettings(
927    NEXUS_AudioCaptureHandle handle,
928    NEXUS_AudioCaptureSettings *pSettings /* [out] */
929    )
930{
931    BSTD_UNUSED(handle);
932    BSTD_UNUSED(pSettings);
933}
934
935NEXUS_Error NEXUS_AudioCapture_SetSettings(
936    NEXUS_AudioCaptureHandle handle,
937    const NEXUS_AudioCaptureSettings *pSettings
938    )
939{
940    BSTD_UNUSED(handle);
941    BSTD_UNUSED(pSettings);
942    return BERR_TRACE(BERR_NOT_SUPPORTED);
943}
944
945void NEXUS_AudioCapture_GetDefaultStartSettings(
946    NEXUS_AudioCaptureStartSettings *pSettings  /* [out] default settings */
947    )
948{
949    BSTD_UNUSED(pSettings);
950}
951
952NEXUS_Error NEXUS_AudioCapture_Start(
953    NEXUS_AudioCaptureHandle handle,
954    const NEXUS_AudioCaptureStartSettings *pSettings
955    )
956{
957    BSTD_UNUSED(handle);
958    BSTD_UNUSED(pSettings);
959    return BERR_TRACE(BERR_NOT_SUPPORTED);
960}
961
962void NEXUS_AudioCapture_Stop(
963    NEXUS_AudioCaptureHandle handle
964    )
965{
966    BSTD_UNUSED(handle);
967}
968
969NEXUS_Error NEXUS_AudioCapture_GetBuffer(
970    NEXUS_AudioCaptureHandle handle,
971    void **ppBuffer,    /* [out] attr{memory=cached} pointer to memory mapped
972                                 region that contains captured data. */
973    size_t *pSize       /* [out] total number of readable, contiguous bytes which the buffers are pointing to */
974    )
975{
976    BSTD_UNUSED(handle);
977    BSTD_UNUSED(ppBuffer);
978    BSTD_UNUSED(pSize);
979    return BERR_TRACE(BERR_NOT_SUPPORTED);
980}
981
982NEXUS_Error NEXUS_AudioCapture_WriteComplete(
983    NEXUS_AudioCaptureHandle handle,
984    size_t amountWritten            /* The number of bytes read from the buffer */
985    )
986{
987    BSTD_UNUSED(handle);
988    BSTD_UNUSED(amountWritten);
989    return BERR_TRACE(BERR_NOT_SUPPORTED);
990}
991
992NEXUS_AudioOutput NEXUS_AudioCapture_GetConnector( /* attr{shutdown=NEXUS_AudioOutput_Shutdown} */
993    NEXUS_AudioCaptureHandle handle
994    )
995{
996    BSTD_UNUSED(handle);
997    return NULL;
998}
999#endif
Note: See TracBrowser for help on using the repository browser.