summaryrefslogtreecommitdiff
path: root/firmware/export/pcm_mixer.h
blob: be10601ffd5cbad08fe932ae5a6483249a87be68 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
/***************************************************************************
 *             __________               __   ___.
 *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
 *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
 *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
 *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
 *                     \/            \/     \/    \/            \/
 * $Id$
 *
 * Copyright (C) 2011 by Michael Sevakis
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 * KIND, either express or implied.
 *
 ****************************************************************************/

#ifndef PCM_MIXER_H
#define PCM_MIXER_H

/** Simple config **/

/* Length of PCM frames (always) */
#if CONFIG_CPU == PP5002
/* There's far less time to do mixing because HW FIFOs are short */
#define MIX_FRAME_SAMPLES 64
#else
/* Assume HW DMA engine is available or sufficient latency exists in the
   PCM pathway */
#define MIX_FRAME_SAMPLES 256
#endif

/* IAUDIO_M5 is very tight on IRAM */
#if (defined(CPU_COLDFIRE) && !defined(IAUDIO_M5)) ||  defined(CPU_PP)
/* For Coldfire, it's just faster
   For PortalPlayer, this also avoids more expensive cache coherency */
#define DOWNMIX_BUF_IBSS        IBSS_ATTR
#else
/* Otherwise can't DMA from IRAM, IRAM is pointless or worse */
#define DOWNMIX_BUF_IBSS
#endif

#if defined(CPU_COLDFIRE) || defined(CPU_PP)
#define MIXER_CALLBACK_ICODE    ICODE_ATTR
#else
#define MIXER_CALLBACK_ICODE
#endif


/** Definitions **/

/* Channels are preassigned for simplicity */
enum pcm_mixer_channel
{
    PCM_MIXER_CHAN_PLAYBACK = 0,
    PCM_MIXER_CHAN_VOICE,
#ifndef HAVE_HARDWARE_BEEP
    PCM_MIXER_CHAN_BEEP,
#endif
    /* Add new channel indexes above this line */
    PCM_MIXER_NUM_CHANNELS,
};

/* Channel playback states */
enum channel_status
{
    CHANNEL_STOPPED = 0,
    CHANNEL_PLAYING,
    CHANNEL_PAUSED,
};

#define MIX_AMP_UNITY    0x00010000
#define MIX_AMP_MUTE     0x00000000


/** Public interfaces **/

/* Start playback on a channel */
void mixer_channel_play_data(enum pcm_mixer_channel channel,
                             pcm_play_callback_type get_more,
                             unsigned char *start, size_t size);

/* Pause or resume a channel (when started) */
void mixer_channel_play_pause(enum pcm_mixer_channel channel, bool play);

/* Stop playback on a channel */
void mixer_channel_stop(enum pcm_mixer_channel channel);

/* Set channel's amplitude factor */
void mixer_channel_set_amplitude(enum pcm_mixer_channel channel,
                                 unsigned int amplitude);

/* Return channel's playback status */
enum channel_status mixer_channel_status(enum pcm_mixer_channel channel);

/* Returns amount data remaining in channel before next callback */
size_t mixer_channel_get_bytes_waiting(enum pcm_mixer_channel channel);

/* Return pointer to channel's playing audio data and the size remaining */
void * mixer_channel_get_buffer(enum pcm_mixer_channel channel, int *count);

/* Calculate peak values for channel */
void mixer_channel_calculate_peaks(enum pcm_mixer_channel channel,
                                   int *left, int *right);

/* Stop ALL channels and PCM and reset state */
void mixer_reset(void);

#endif /* PCM_MIXER_H */