~ubuntu-dev/ubuntu/lucid/mpd/lucid-201002101854

« back to all changes in this revision

Viewing changes to src/pcm_utils.c

  • Committer: Bazaar Package Importer
  • Author(s): Charles Majola
  • Date: 2005-02-15 10:43:58 UTC
  • Revision ID: james.westby@ubuntu.com-20050215104358-w8b7yaqqfmsoxj5k
Tags: upstream-0.11.5
ImportĀ upstreamĀ versionĀ 0.11.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* the Music Player Daemon (MPD)
 
2
 * (c)2003-2004 by Warren Dukes (shank@mercury.chem.pitt.edu)
 
3
 * This project's homepage is: http://www.musicpd.org
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or modify
 
6
 * it under the terms of the GNU General Public License as published by
 
7
 * the Free Software Foundation; either version 2 of the License, or
 
8
 * (at your option) any later version.
 
9
 *
 
10
 * This program is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 * GNU General Public License for more details.
 
14
 * You should have received a copy of the GNU General Public License
 
15
 * along with this program; if not, write to the Free Software
 
16
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
17
 */
 
18
 
 
19
 
 
20
#include "pcm_utils.h"
 
21
 
 
22
#include "mpd_types.h"
 
23
#include "log.h"
 
24
 
 
25
#include <string.h>
 
26
#include <math.h>
 
27
#include <assert.h>
 
28
 
 
29
void pcm_changeBufferEndianness(char * buffer, int bufferSize, int bits) {
 
30
        char temp;
 
31
 
 
32
        switch(bits) {
 
33
        case 16:
 
34
                while(bufferSize) {
 
35
                        temp = *buffer;
 
36
                        *buffer = *(buffer+1);
 
37
                        *(buffer+1) = temp;
 
38
                        bufferSize-=2;
 
39
                }
 
40
                break;
 
41
        }
 
42
}
 
43
 
 
44
void pcm_volumeChange(char * buffer, int bufferSize, AudioFormat * format,
 
45
                int volume)
 
46
{
 
47
        mpd_sint32 temp32;
 
48
        mpd_sint8 * buffer8 = (mpd_sint8 *)buffer;
 
49
        mpd_sint16 * buffer16 = (mpd_sint16 *)buffer;
 
50
 
 
51
        if(volume>=1000) return;
 
52
        
 
53
        if(volume<=0) {
 
54
                memset(buffer,0,bufferSize);
 
55
                return;
 
56
        }
 
57
 
 
58
        switch(format->bits) {
 
59
        case 16:
 
60
                while(bufferSize>0) {
 
61
                        temp32 = *buffer16;
 
62
                        temp32*= volume;
 
63
                        temp32/=1000;
 
64
                        *buffer16 = temp32>32767 ? 32767 : 
 
65
                                        (temp32<-32768 ? -32768 : temp32);
 
66
                        buffer16++;
 
67
                        bufferSize-=2;
 
68
                }
 
69
                break;
 
70
        case 8:
 
71
                while(bufferSize>0) {
 
72
                        temp32 = *buffer8;
 
73
                        temp32*= volume;
 
74
                        temp32/=1000;
 
75
                        *buffer8 = temp32>127 ? 127 : 
 
76
                                        (temp32<-128 ? -128 : temp32);
 
77
                        buffer8++;
 
78
                        bufferSize--;
 
79
                }
 
80
                break;
 
81
        default:
 
82
                ERROR("%i bits not supported by pcm_volumeChange!\n",
 
83
                                format->bits);
 
84
                exit(EXIT_FAILURE);
 
85
        }
 
86
}
 
87
 
 
88
void pcm_add(char * buffer1, char * buffer2, size_t bufferSize1, 
 
89
                size_t bufferSize2, int vol1, int vol2, AudioFormat * format)
 
90
{
 
91
        mpd_sint32 temp32;
 
92
        mpd_sint8 * buffer8_1 = (mpd_sint8 *)buffer1;
 
93
        mpd_sint8 * buffer8_2 = (mpd_sint8 *)buffer2;
 
94
        mpd_sint16 * buffer16_1 = (mpd_sint16 *)buffer1;
 
95
        mpd_sint16 * buffer16_2 = (mpd_sint16 *)buffer2;
 
96
 
 
97
        switch(format->bits) {
 
98
        case 16:
 
99
                while(bufferSize1>0 && bufferSize2>0) {
 
100
                        temp32 = (vol1*(*buffer16_1)+vol2*(*buffer16_2))/1000;
 
101
                        *buffer16_1 = temp32>32767 ? 32767 : 
 
102
                                        (temp32<-32768 ? -32768 : temp32);
 
103
                        buffer16_1++;
 
104
                        buffer16_2++;
 
105
                        bufferSize1-=2;
 
106
                        bufferSize2-=2;
 
107
                }
 
108
                if(bufferSize2>0) memcpy(buffer16_1,buffer16_2,bufferSize2);
 
109
                break;
 
110
        case 8:
 
111
                while(bufferSize1>0 && bufferSize2>0) {
 
112
                        temp32 = (vol1*(*buffer8_1)+vol2*(*buffer8_2))/1000;
 
113
                        *buffer8_1 = temp32>127 ? 127 : 
 
114
                                        (temp32<-128 ? -128 : temp32);
 
115
                        buffer8_1++;
 
116
                        buffer8_2++;
 
117
                        bufferSize1--;
 
118
                        bufferSize2--;
 
119
                }
 
120
                if(bufferSize2>0) memcpy(buffer8_1,buffer8_2,bufferSize2);
 
121
                break;
 
122
        default:
 
123
                ERROR("%i bits not supported by pcm_add!\n",format->bits);
 
124
                exit(EXIT_FAILURE);
 
125
        }
 
126
}
 
127
 
 
128
void pcm_mix(char * buffer1, char * buffer2, size_t bufferSize1, 
 
129
                size_t bufferSize2, AudioFormat * format, float portion1)
 
130
{
 
131
        int vol1;
 
132
        float s = sin(M_PI_2*portion1);
 
133
        s*=s;
 
134
        
 
135
        vol1 = s*1000+0.5;
 
136
        vol1 = vol1>1000 ? 1000 : ( vol1<0 ? 0 : vol1 );
 
137
 
 
138
        pcm_add(buffer1,buffer2,bufferSize1,bufferSize2,vol1,1000-vol1,format);
 
139
}
 
140
 
 
141
 
 
142
/* outFormat bits must be 16 and channels must be 2! */
 
143
void pcm_convertAudioFormat(AudioFormat * inFormat, char * inBuffer, size_t
 
144
                inSize, AudioFormat * outFormat, char * outBuffer)
 
145
{
 
146
        static char * bitConvBuffer = NULL;
 
147
        static int bitConvBufferLength = 0;
 
148
        static char * channelConvBuffer = NULL;
 
149
        static int channelConvBufferLength = 0;
 
150
        char * dataChannelConv;
 
151
        int dataChannelLen;
 
152
        char * dataBitConv;
 
153
        int dataBitLen;
 
154
 
 
155
        assert(outFormat->bits==16);
 
156
        assert(outFormat->channels==2);
 
157
 
 
158
        /* converts */
 
159
        switch(inFormat->bits) {
 
160
        case 8:
 
161
                dataBitLen = inSize << 1;
 
162
                if(dataBitLen > bitConvBufferLength) {
 
163
                        bitConvBuffer = realloc(bitConvBuffer, dataBitLen);
 
164
                        bitConvBufferLength = dataBitLen;
 
165
                }
 
166
                dataBitConv = bitConvBuffer;
 
167
                {
 
168
                        mpd_sint8 * in = (mpd_sint8 *)inBuffer;
 
169
                        mpd_sint16 * out = (mpd_sint16 *)dataBitConv;
 
170
                        int i;
 
171
                        for(i=0; i<inSize; i++) {
 
172
                                *out++ = (*in++) << 8;
 
173
                        }
 
174
                }
 
175
                break;
 
176
        case 16:
 
177
                dataBitConv = inBuffer;
 
178
                dataBitLen = inSize;
 
179
                break;
 
180
        case 24:
 
181
                /* put dithering code from mp3_decode here */
 
182
        default:
 
183
                ERROR("only 8 or 16 bits are supported for conversion!\n");
 
184
                exit(EXIT_FAILURE);
 
185
        }
 
186
 
 
187
        /* converts only between 16 bit audio between mono and stereo */
 
188
        switch(inFormat->channels) {
 
189
        case 1:
 
190
                dataChannelLen = (dataBitLen >> 1) << 2;
 
191
                if(dataChannelLen > channelConvBufferLength) {
 
192
                        channelConvBuffer = realloc(channelConvBuffer,
 
193
                                        dataChannelLen);
 
194
                        channelConvBufferLength = dataChannelLen;
 
195
                }
 
196
                dataChannelConv = channelConvBuffer;
 
197
                {
 
198
                        mpd_sint16 * in = (mpd_sint16 *)dataBitConv;
 
199
                        mpd_sint16 * out = (mpd_sint16 *)dataChannelConv;
 
200
                        int i, inSamples = dataBitLen >> 1;
 
201
                        for(i=0;i<inSamples;i++) {
 
202
                                *out++ = *in;
 
203
                                *out++ = *in++;
 
204
                        }
 
205
                }
 
206
                break;
 
207
        case 2:
 
208
                dataChannelConv = dataBitConv;
 
209
                dataChannelLen = dataBitLen;
 
210
                break;
 
211
        default:
 
212
                ERROR("only 1 or 2 channels are supported for conversion!\n");
 
213
                exit(EXIT_FAILURE);
 
214
        }
 
215
 
 
216
        if(inFormat->sampleRate == outFormat->sampleRate) {
 
217
                memcpy(outBuffer,dataChannelConv,dataChannelLen);
 
218
        }
 
219
        else {
 
220
                /* only works if outFormat is 16-bit stereo! */
 
221
                /* resampling code blatantly ripped from ESD */
 
222
                mpd_sint32 rd_dat = 0;
 
223
                mpd_uint32 wr_dat = 0;
 
224
                mpd_sint16 lsample, rsample;
 
225
                register mpd_sint16 * out = (mpd_sint16 *)outBuffer;
 
226
                register mpd_sint16 * in = (mpd_sint16 *)dataChannelConv;
 
227
                const int shift = sizeof(mpd_sint16);
 
228
                mpd_uint32 nlen = ((( dataChannelLen >> shift) * 
 
229
                                (mpd_uint32)(outFormat->sampleRate)) /
 
230
                                inFormat->sampleRate);
 
231
                nlen <<= shift;
 
232
 
 
233
                while( wr_dat < nlen / shift) {
 
234
                        rd_dat = wr_dat * inFormat->sampleRate / 
 
235
                                outFormat->sampleRate;
 
236
                        rd_dat &= ~1;
 
237
 
 
238
                        lsample = in[ rd_dat++ ];
 
239
                        rsample = in[ rd_dat++ ];
 
240
 
 
241
                        out[ wr_dat++ ] = lsample;
 
242
                        out[ wr_dat++ ] = rsample;
 
243
                }
 
244
        }
 
245
 
 
246
        return;
 
247
}
 
248
 
 
249
size_t pcm_sizeOfOutputBufferForAudioFormatConversion(AudioFormat * inFormat,
 
250
                char * inBuffer, size_t inSize, AudioFormat * outFormat)
 
251
{
 
252
        const int shift = sizeof(mpd_sint16);
 
253
        size_t outSize = inSize;
 
254
 
 
255
        switch(inFormat->bits) {
 
256
        case 8:
 
257
                outSize = outSize << 1;
 
258
                break;
 
259
        case 16:
 
260
                break;
 
261
        default:
 
262
                ERROR("only 8 or 16 bits are supported for conversion!\n");
 
263
                exit(EXIT_FAILURE);
 
264
        }
 
265
 
 
266
        switch(inFormat->channels) {
 
267
        case 1:
 
268
                outSize = (outSize >> 1) << 2;
 
269
                break;
 
270
        case 2:
 
271
                break;
 
272
        default:
 
273
                ERROR("only 1 or 2 channels are supported for conversion!\n");
 
274
                exit(EXIT_FAILURE);
 
275
        }
 
276
        
 
277
        outSize = (((outSize >> shift) * (mpd_uint32)(outFormat->sampleRate)) /
 
278
                                inFormat->sampleRate);
 
279
 
 
280
        outSize <<= shift;
 
281
 
 
282
        return outSize;
 
283
}