~ubuntu-branches/ubuntu/lucid/mpg123/lucid

« back to all changes in this revision

Viewing changes to src/audio.c

Tags: upstream-0.60
ImportĀ upstreamĀ versionĀ 0.60

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
        audio: audio output interface
 
3
 
 
4
        copyright ?-2006 by the mpg123 project - free software under the terms of the LGPL 2.1
 
5
        see COPYING and AUTHORS files in distribution or http://mpg123.de
 
6
        initially written by Michael Hipp
 
7
*/
 
8
 
 
9
#include <stdlib.h>
 
10
#include "config.h"
 
11
#include "mpg123.h"
 
12
 
 
13
void audio_info_struct_init(struct audio_info_struct *ai)
 
14
{
 
15
  ai->fn = -1;
 
16
  ai->rate = -1;
 
17
  ai->gain = -1;
 
18
  ai->output = -1;
 
19
  ai->handle = NULL;
 
20
#ifdef ALSA
 
21
  ai->alsa_format.format = -1;
 
22
  ai->alsa_format.rate = -1;
 
23
  ai->alsa_format.channels = -1;
 
24
#endif
 
25
  ai->device = NULL;
 
26
  ai->channels = -1;
 
27
  ai->format = -1;
 
28
}
 
29
 
 
30
 
 
31
void audio_info_struct_dump(struct audio_info_struct *ai)
 
32
{
 
33
        fprintf(stderr, "ai->fn=%d\n", ai->fn);
 
34
        fprintf(stderr, "ai->handle=%p\n", ai->handle);
 
35
        fprintf(stderr, "ai->rate=%ld\n", ai->rate);
 
36
        fprintf(stderr, "ai->gain=%ld\n", ai->gain);
 
37
        fprintf(stderr, "ai->output=%d\n", ai->output);
 
38
        fprintf(stderr, "ai->device='%s'\n", ai->device);
 
39
        fprintf(stderr, "ai->channels=%d\n", ai->channels);
 
40
        fprintf(stderr, "ai->format=%d\n", ai->format);
 
41
}
 
42
 
 
43
 
 
44
#define NUM_CHANNELS 2
 
45
#define NUM_ENCODINGS 6
 
46
#define NUM_RATES 10
 
47
 
 
48
struct audio_name audio_val2name[NUM_ENCODINGS+1] = {
 
49
 { AUDIO_FORMAT_SIGNED_16  , "signed 16 bit" , "s16 " } ,
 
50
 { AUDIO_FORMAT_UNSIGNED_16, "unsigned 16 bit" , "u16 " } ,  
 
51
 { AUDIO_FORMAT_UNSIGNED_8 , "unsigned 8 bit" , "u8  " } ,
 
52
 { AUDIO_FORMAT_SIGNED_8   , "signed 8 bit" , "s8  " } ,
 
53
 { AUDIO_FORMAT_ULAW_8     , "mu-law (8 bit)" , "ulaw " } ,
 
54
 { AUDIO_FORMAT_ALAW_8     , "a-law (8 bit)" , "alaw " } ,
 
55
 { -1 , NULL }
 
56
};
 
57
 
 
58
#if 0
 
59
static char *channel_name[NUM_CHANNELS] = 
 
60
 { "mono" , "stereo" };
 
61
#endif
 
62
 
 
63
static int channels[NUM_CHANNELS] = { 1 , 2 };
 
64
static int rates[NUM_RATES] = { 
 
65
         8000, 11025, 12000, 
 
66
        16000, 22050, 24000,
 
67
        32000, 44100, 48000,
 
68
        8000    /* 8000 = dummy for user forced */
 
69
 
 
70
};
 
71
static int encodings[NUM_ENCODINGS] = {
 
72
 AUDIO_FORMAT_SIGNED_16, 
 
73
 AUDIO_FORMAT_UNSIGNED_16,
 
74
 AUDIO_FORMAT_UNSIGNED_8,
 
75
 AUDIO_FORMAT_SIGNED_8,
 
76
 AUDIO_FORMAT_ULAW_8,
 
77
 AUDIO_FORMAT_ALAW_8
 
78
};
 
79
 
 
80
static char capabilities[NUM_CHANNELS][NUM_ENCODINGS][NUM_RATES];
 
81
 
 
82
void audio_capabilities(struct audio_info_struct *ai)
 
83
{
 
84
        int fmts;
 
85
        int i,j,k,k1=NUM_RATES-1;
 
86
        struct audio_info_struct ai1 = *ai;
 
87
 
 
88
        if (param.outmode != DECODE_AUDIO) {
 
89
                memset(capabilities,1,sizeof(capabilities));
 
90
                return;
 
91
        }
 
92
 
 
93
        memset(capabilities,0,sizeof(capabilities));
 
94
        if(param.force_rate) {
 
95
                rates[NUM_RATES-1] = param.force_rate;
 
96
                k1 = NUM_RATES;
 
97
        }
 
98
 
 
99
        if(audio_open(&ai1) < 0) {
 
100
                perror("audio");
 
101
                exit(1);
 
102
        }
 
103
 
 
104
        for(i=0;i<NUM_CHANNELS;i++) {
 
105
                for(j=0;j<NUM_RATES;j++) {
 
106
                        ai1.channels = channels[i];
 
107
                        ai1.rate = rates[j];
 
108
                        fmts = audio_get_formats(&ai1);
 
109
                        if(fmts < 0)
 
110
                                continue;
 
111
                        for(k=0;k<NUM_ENCODINGS;k++) {
 
112
                                if((fmts & encodings[k]) == encodings[k])
 
113
                                        capabilities[i][k][j] = 1;
 
114
                        }
 
115
                }
 
116
        }
 
117
 
 
118
        audio_close(&ai1);
 
119
 
 
120
        if(param.verbose > 1) {
 
121
                fprintf(stderr,"\nAudio capabilities:\n        |");
 
122
                for(j=0;j<NUM_ENCODINGS;j++) {
 
123
                        fprintf(stderr," %5s |",audio_val2name[j].sname);
 
124
                }
 
125
                fprintf(stderr,"\n --------------------------------------------------------\n");
 
126
                for(k=0;k<k1;k++) {
 
127
                        fprintf(stderr," %5d  |",rates[k]);
 
128
                        for(j=0;j<NUM_ENCODINGS;j++) {
 
129
                                if(capabilities[0][j][k]) {
 
130
                                        if(capabilities[1][j][k])
 
131
                                                fprintf(stderr,"  M/S  |");
 
132
                                        else
 
133
                                                fprintf(stderr,"   M   |");
 
134
                                }
 
135
                                else if(capabilities[1][j][k])
 
136
                                        fprintf(stderr,"   S   |");
 
137
                                else
 
138
                                        fprintf(stderr,"       |");
 
139
                        }
 
140
                        fprintf(stderr,"\n");
 
141
                }
 
142
                fprintf(stderr,"\n");
 
143
        }
 
144
}
 
145
 
 
146
static int rate2num(int r)
 
147
{
 
148
        int i;
 
149
        for(i=0;i<NUM_RATES;i++) 
 
150
                if(rates[i] == r)
 
151
                        return i;
 
152
        return -1;
 
153
}
 
154
 
 
155
 
 
156
static int audio_fit_cap_helper(struct audio_info_struct *ai,int rn,int f0,int f2,int c)
 
157
{
 
158
        int i;
 
159
 
 
160
        if(rn >= 0) {
 
161
                for(i=f0;i<f2;i++) {
 
162
                        if(capabilities[c][i][rn]) {
 
163
                                ai->rate = rates[rn];
 
164
                                ai->format = encodings[i];
 
165
                                ai->channels = channels[c];
 
166
                                return 1;
 
167
                        }
 
168
                }
 
169
        }
 
170
        return 0;
 
171
 
 
172
}
 
173
 
 
174
/*
 
175
 * c=num of channels of stream
 
176
 * r=rate of stream
 
177
 */
 
178
void audio_fit_capabilities(struct audio_info_struct *ai,int c,int r)
 
179
{
 
180
        int rn;
 
181
        int f0=0;
 
182
        
 
183
        if(param.force_8bit) {
 
184
                f0 = 2;
 
185
        }
 
186
 
 
187
        c--; /* stereo=1 ,mono=0 */
 
188
 
 
189
        if(param.force_mono >= 0)
 
190
                c = 0;
 
191
        if(param.force_stereo)
 
192
                c = 1;
 
193
 
 
194
        if(param.force_rate) {
 
195
                rn = rate2num(param.force_rate);
 
196
                if(audio_fit_cap_helper(ai,rn,f0,2,c))
 
197
                        return;
 
198
                if(audio_fit_cap_helper(ai,rn,2,NUM_ENCODINGS,c))
 
199
                        return;
 
200
 
 
201
                if(c == 1 && !param.force_stereo)
 
202
                        c = 0;
 
203
                else if(c == 0 && !param.force_mono)
 
204
                        c = 1;
 
205
 
 
206
                if(audio_fit_cap_helper(ai,rn,f0,2,c))
 
207
                        return;
 
208
                if(audio_fit_cap_helper(ai,rn,2,NUM_ENCODINGS,c))
 
209
                        return;
 
210
 
 
211
                fprintf(stderr,"No supported rate found!\n");
 
212
                exit(1);
 
213
        }
 
214
 
 
215
        rn = rate2num(r>>0);
 
216
        if(audio_fit_cap_helper(ai,rn,f0,2,c))
 
217
                return;
 
218
        rn = rate2num(r>>1);
 
219
        if(audio_fit_cap_helper(ai,rn,f0,2,c))
 
220
                return;
 
221
        rn = rate2num(r>>2);
 
222
        if(audio_fit_cap_helper(ai,rn,f0,2,c))
 
223
                return;
 
224
 
 
225
        rn = rate2num(r>>0);
 
226
        if(audio_fit_cap_helper(ai,rn,2,NUM_ENCODINGS,c))
 
227
                return;
 
228
        rn = rate2num(r>>1);
 
229
        if(audio_fit_cap_helper(ai,rn,2,NUM_ENCODINGS,c))
 
230
                return;
 
231
        rn = rate2num(r>>2);
 
232
        if(audio_fit_cap_helper(ai,rn,2,NUM_ENCODINGS,c))
 
233
                return;
 
234
 
 
235
 
 
236
        if(c == 1 && !param.force_stereo)
 
237
                c = 0;
 
238
        else if(c == 0 && !param.force_mono)
 
239
                c = 1;
 
240
 
 
241
        rn = rate2num(r>>0);
 
242
        if(audio_fit_cap_helper(ai,rn,f0,2,c))
 
243
                return;
 
244
        rn = rate2num(r>>1);
 
245
        if(audio_fit_cap_helper(ai,rn,f0,2,c))
 
246
                return;
 
247
        rn = rate2num(r>>2);
 
248
        if(audio_fit_cap_helper(ai,rn,f0,2,c))
 
249
                return;
 
250
 
 
251
        rn = rate2num(r>>0);
 
252
        if(audio_fit_cap_helper(ai,rn,2,NUM_ENCODINGS,c))
 
253
                return;
 
254
        rn = rate2num(r>>1);
 
255
        if(audio_fit_cap_helper(ai,rn,2,NUM_ENCODINGS,c))
 
256
                return;
 
257
        rn = rate2num(r>>2);
 
258
        if(audio_fit_cap_helper(ai,rn,2,NUM_ENCODINGS,c))
 
259
                return;
 
260
 
 
261
        fprintf(stderr,"No supported rate found!\n");
 
262
        exit(1);
 
263
}
 
264
 
 
265
char *audio_encoding_name(int format)
 
266
{
 
267
        int i;
 
268
 
 
269
        for(i=0;i<NUM_ENCODINGS;i++) {
 
270
                if(audio_val2name[i].val == format)
 
271
                        return audio_val2name[i].name;
 
272
        }
 
273
        return "Unknown";
 
274
}