Statistics
| Branch: | Revision:

root / oss.c @ 08cea4ee

History | View | Annotate | Download (11.6 kB)

1
/*
2
 * QEMU OSS Audio output driver
3
 * 
4
 * Copyright (c) 2003 Vassili Karpov (malc)
5
 * 
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 */
24
#include <fcntl.h>
25
#include <errno.h>
26
#include <stdio.h>
27
#include <unistd.h>
28
#include <string.h>
29
#include <stdlib.h>
30
#include <limits.h>
31
#include <inttypes.h>
32
#include <sys/types.h>
33
#include <sys/ioctl.h>
34
#include <sys/soundcard.h>
35

    
36
#include "vl.h"
37

    
38
/* http://www.df.lth.se/~john_e/gems/gem002d.html */
39
/* http://www.multi-platforms.com/Tips/PopCount.htm */
40
static inline uint32_t popcount (uint32_t u)
41
{
42
  u = ((u&0x55555555) + ((u>>1)&0x55555555));
43
  u = ((u&0x33333333) + ((u>>2)&0x33333333));
44
  u = ((u&0x0f0f0f0f) + ((u>>4)&0x0f0f0f0f));
45
  u = ((u&0x00ff00ff) + ((u>>8)&0x00ff00ff));
46
  u = ( u&0x0000ffff) + (u>>16);
47
  return u;
48
}
49

    
50
static inline uint32_t lsbindex (uint32_t u)
51
{
52
  return popcount ((u&-u)-1);
53
}
54

    
55
#define MIN(a, b) ((a)>(b)?(b):(a))
56
#define MAX(a, b) ((a)<(b)?(b):(a))
57

    
58
#define DEREF(x) (void)x
59
#define log(...) fprintf (stderr, "oss: " __VA_ARGS__)
60
#define ERRFail(...) do {                                       \
61
    int _errno = errno;                                         \
62
    fprintf (stderr, "oss: " __VA_ARGS__);                      \
63
    fprintf (stderr, "system error: %s\n", strerror (_errno));  \
64
    abort ();                                                   \
65
} while (0)
66
#define Fail(...) do {                          \
67
    fprintf (stderr, "oss: " __VA_ARGS__);      \
68
    fprintf (stderr, "\n");                     \
69
    abort ();                                   \
70
} while (0)
71

    
72
#ifdef DEBUG_OSS
73
#define lwarn(...) fprintf (stderr, "oss: " __VA_ARGS__)
74
#define linfo(...) fprintf (stderr, "oss: " __VA_ARGS__)
75
#define ldebug(...) fprintf (stderr, "oss: " __VA_ARGS__)
76
#else
77
#define lwarn(...)
78
#define linfo(...)
79
#define ldebug(...)
80
#endif
81

    
82

    
83
#define IOCTL(args) do {                        \
84
  int ret = ioctl args;                         \
85
  if (-1 == ret) {                              \
86
    ERRFail (#args);                            \
87
  }                                             \
88
  ldebug ("ioctl " #args " = %d\n", ret);       \
89
} while (0)
90

    
91
static int audio_fd = -1;
92
static int freq;
93
static int conf_nfrags = 4;
94
static int conf_fragsize;
95
static int nfrags;
96
static int fragsize;
97
static int bufsize;
98
static int nchannels;
99
static int fmt;
100
static int rpos;
101
static int wpos;
102
static int atom;
103
static int live;
104
static int leftover;
105
static int bytes_per_second;
106
static void *buf;
107
static enum {DONT, DSP, TID} estimate = TID;
108

    
109
static void (*copy_fn)(void *, void *, int);
110

    
111
static void copy_no_conversion (void *dst, void *src, int size)
112
{
113
    memcpy (dst, src, size);
114
}
115

    
116
static void copy_u16_to_s16 (void *dst, void *src, int size)
117
{
118
    int i;
119
    uint16_t *out, *in;
120

    
121
    out = dst;
122
    in = src;
123

    
124
    for (i = 0; i < size / 2; i++) {
125
        out[i] = in[i] + 0x8000;
126
    }
127
}
128

    
129
static void pab (struct audio_buf_info *abinfo)
130
{
131
    DEREF (abinfo);
132

    
133
    ldebug ("fragments %d, fragstotal %d, fragsize %d, bytes %d\n"
134
            "rpos %d, wpos %d, live %d\n",
135
            abinfo->fragments,
136
            abinfo->fragstotal,
137
            abinfo->fragsize,
138
            abinfo->bytes,
139
            rpos, wpos, live);
140
}
141

    
142
void AUD_reset (int rfreq, int rnchannels, audfmt_e rfmt)
143
{
144
    int fmt_;
145
    int bits16;
146

    
147
    if (-1 == audio_fd) {
148
        AUD_open (rfreq, rnchannels, rfmt);
149
        return;
150
    }
151

    
152
    switch (rfmt) {
153
    case AUD_FMT_U8:
154
        bits16 = 0;
155
        fmt_ = AFMT_U8;
156
        copy_fn = copy_no_conversion;
157
        atom = 1;
158
        break;
159

    
160
    case AUD_FMT_S8:
161
        Fail ("can not play 8bit signed");
162

    
163
    case AUD_FMT_S16:
164
        bits16 = 1;
165
        fmt_ = AFMT_S16_LE;
166
        copy_fn = copy_no_conversion;
167
        atom = 2;
168
        break;
169

    
170
    case AUD_FMT_U16:
171
        bits16 = 1;
172
        fmt_ = AFMT_S16_LE;
173
        copy_fn = copy_u16_to_s16;
174
        atom = 2;
175
        break;
176

    
177
    default:
178
        abort ();
179
    }
180

    
181
    if ((fmt_ == fmt) && (bits16 + 1 == nchannels) && (rfreq == freq))
182
        return;
183
    else {
184
        AUD_open (rfreq, rnchannels, rfmt);
185
    }
186
}
187

    
188
void AUD_open (int rfreq, int rnchannels, audfmt_e rfmt)
189
{
190
    int fmt_;
191
    int mmmmssss;
192
    struct audio_buf_info abinfo;
193
    int _fmt;
194
    int _freq;
195
    int _nchannels;
196
    int bits16;
197

    
198
    bits16 = 0;
199

    
200
    switch (rfmt) {
201
    case AUD_FMT_U8:
202
        bits16 = 0;
203
        fmt_ = AFMT_U8;
204
        copy_fn = copy_no_conversion;
205
        atom = 1;
206
        break;
207

    
208
    case AUD_FMT_S8:
209
        Fail ("can not play 8bit signed");
210

    
211
    case AUD_FMT_S16:
212
        bits16 = 1;
213
        fmt_ = AFMT_S16_LE;
214
        copy_fn = copy_no_conversion;
215
        atom = 2;
216
        break;
217

    
218
    case AUD_FMT_U16:
219
        bits16 = 1;
220
        fmt_ = AFMT_S16_LE;
221
        copy_fn = copy_u16_to_s16;
222
        atom = 2;
223
        break;
224

    
225
    default:
226
        abort ();
227
    }
228

    
229
    if (buf) {
230
        free (buf);
231
        buf = 0;
232
    }
233

    
234
    if (-1 != audio_fd)
235
        close (audio_fd);
236

    
237
    audio_fd = open ("/dev/dsp", O_WRONLY | O_NONBLOCK);
238
    if (-1 == audio_fd) {
239
        ERRFail ("can not open /dev/dsp");
240
    }
241

    
242
    _fmt = fmt_;
243
    _freq = rfreq;
244
    _nchannels = rnchannels;
245

    
246
    IOCTL ((audio_fd, SNDCTL_DSP_RESET, 1));
247
    IOCTL ((audio_fd, SNDCTL_DSP_SAMPLESIZE, &_fmt));
248
    IOCTL ((audio_fd, SNDCTL_DSP_CHANNELS, &_nchannels));
249
    IOCTL ((audio_fd, SNDCTL_DSP_SPEED, &_freq));
250
    IOCTL ((audio_fd, SNDCTL_DSP_NONBLOCK));
251

    
252
    /* from oss.pdf:
253

254
    The argument to this call is an integer encoded as 0xMMMMSSSS (in
255
    hex). The 16 least significant bits determine the fragment
256
    size. The size is 2^SSSS. For examp le SSSS=0008 gives fragment
257
    size of 256 bytes (2^8). The minimum is 16 bytes (SSSS=4) and the
258
    maximum is total_buffer_size/2. Some devices or processor
259
    architectures may require larger fragments - in this case the
260
    requested fragment size is automatically increased.
261

262
    So ahem... 4096 = 2^12, and grand total 0x0004000c
263
    */
264

    
265
    mmmmssss = (conf_nfrags << 16) | conf_fragsize;
266
    IOCTL ((audio_fd, SNDCTL_DSP_SETFRAGMENT, &mmmmssss));
267

    
268
    linfo ("_fmt = %d, fmt = %d\n"
269
           "_channels = %d, rnchannels = %d\n"
270
           "_freq = %d, freq = %d\n",
271
           _fmt, fmt_,
272
           _nchannels, rnchannels,
273
           _freq, rfreq);
274

    
275
    if (_fmt != fmt_) {
276
        Fail ("format %d != %d", _fmt, fmt_);
277
    }
278

    
279
    if (_nchannels != rnchannels) {
280
        Fail ("channels %d != %d", _nchannels, rnchannels);
281
    }
282

    
283
    if (_freq != rfreq) {
284
        Fail ("freq %d != %d", _freq, rfreq);
285
    }
286

    
287
    IOCTL ((audio_fd, SNDCTL_DSP_GETOSPACE, &abinfo));
288

    
289
    nfrags = abinfo.fragstotal;
290
    fragsize = abinfo.fragsize;
291
    freq = _freq;
292
    fmt = _fmt;
293
    nchannels = rnchannels;
294
    atom <<= nchannels >>  1;
295
    bufsize = nfrags * fragsize;
296

    
297
    bytes_per_second = (freq << (nchannels >> 1)) << bits16;
298

    
299
    linfo ("bytes per second %d\n", bytes_per_second);
300

    
301
    linfo ("fragments %d, fragstotal %d, fragsize %d, bytes %d, bufsize %d\n",
302
           abinfo.fragments,
303
           abinfo.fragstotal,
304
           abinfo.fragsize,
305
           abinfo.bytes,
306
           bufsize);
307

    
308
    if (NULL == buf) {
309
        buf = malloc (bufsize);
310
        if (NULL == buf) {
311
            abort ();
312
        }
313
    }
314

    
315
    rpos = 0;
316
    wpos = 0;
317
    live = 0;
318
}
319

    
320
int AUD_write (void *in_buf, int size)
321
{
322
    int to_copy, temp;
323
    uint8_t *in, *out;
324

    
325
    to_copy = MIN (bufsize - live, size);
326

    
327
    temp = to_copy;
328

    
329
    in = in_buf;
330
    out = buf;
331

    
332
    while (temp) {
333
        int copy;
334

    
335
        copy = MIN (temp, bufsize - wpos);
336
        copy_fn (out + wpos, in, copy);
337

    
338
        wpos += copy;
339
        if (wpos == bufsize) {
340
            wpos = 0;
341
        }
342

    
343
        temp -= copy;
344
        in += copy;
345
        live += copy;
346
    }
347

    
348
    return to_copy;
349
}
350

    
351
void AUD_run (void)
352
{
353
    int res;
354
    int bytes;
355
    struct audio_buf_info abinfo;
356

    
357
    if (0 == live)
358
        return;
359

    
360
    res = ioctl (audio_fd, SNDCTL_DSP_GETOSPACE, &abinfo);
361

    
362
    if (-1 == res) {
363
        int err;
364

    
365
        err = errno;
366
        lwarn ("SNDCTL_DSP_GETOSPACE failed with %s\n", strerror (err));
367
    }
368

    
369
    bytes = abinfo.bytes;
370
    bytes = MIN (live, bytes);
371
#if 0
372
    bytes = (bytes / fragsize) * fragsize;
373
#endif
374

    
375
    while (bytes) {
376
        int left, play, written;
377

    
378
        left = bufsize - rpos;
379
        play = MIN (left, bytes);
380
        written = write (audio_fd, (void *) ((uint32_t) buf + rpos), play);
381

    
382
        if (-1 == written) {
383
            if (EAGAIN == errno || EINTR == errno) {
384
                return;
385
            }
386
            else {
387
                ERRFail ("write audio");
388
            }
389
        }
390

    
391
        play = written;
392
        live -= play;
393
        rpos += play;
394
        bytes -= play;
395

    
396
        if (rpos == bufsize) {
397
            rpos = 0;
398
        }
399
    }
400
}
401

    
402
static int get_dsp_bytes (void)
403
{
404
    int res;
405
    struct count_info info;
406

    
407
    res = ioctl (audio_fd, SNDCTL_DSP_GETOPTR, &info);
408
    if (-1 == res) {
409
        int err;
410

    
411
        err = errno;
412
        lwarn ("SNDCTL_DSP_GETOPTR failed with %s\n", strerror (err));
413
        return -1;
414
    }
415
    else {
416
        ldebug ("bytes %d\n", info.bytes);
417
        return info.bytes;
418
    }
419
}
420

    
421
void AUD_adjust_estimate (int _leftover)
422
{
423
    leftover = _leftover;
424
}
425

    
426
int AUD_get_free (void)
427
{
428
    int free, elapsed;
429

    
430
    free = bufsize - live;
431

    
432
    if (0 == free)
433
        return 0;
434

    
435
    elapsed = free;
436
    switch (estimate) {
437
    case DONT:
438
        break;
439

    
440
    case DSP:
441
        {
442
            static int old_bytes;
443
            int bytes;
444

    
445
            bytes = get_dsp_bytes ();
446
            if (bytes <= 0)
447
                return free;
448

    
449
            elapsed = bytes - old_bytes;
450
            old_bytes = bytes;
451
            ldebug ("dsp elapsed %d bytes\n", elapsed);
452
            break;
453
        }
454

    
455
    case TID:
456
        {
457
            static uint64_t old_ticks;
458
            uint64_t ticks, delta;
459
            uint64_t ua_elapsed;
460
            uint64_t al_elapsed;
461

    
462
            ticks = cpu_get_ticks ();
463
            delta = ticks - old_ticks;
464
            old_ticks = ticks;
465

    
466
            ua_elapsed = (delta * bytes_per_second) / ticks_per_sec;
467
            al_elapsed = ua_elapsed & ~3ULL;
468

    
469
            ldebug ("tid elapsed %llu bytes\n", ua_elapsed);
470

    
471
            if (al_elapsed > (uint64_t) INT_MAX)
472
                elapsed = INT_MAX;
473
            else
474
                elapsed = al_elapsed;
475

    
476
            elapsed += leftover;
477
        }
478
    }
479

    
480
    if (elapsed > free) {
481
        lwarn ("audio can not keep up elapsed %d free %d\n", elapsed, free);
482
        return free;
483
    }
484
    else {
485
        return elapsed;
486
    }
487
}
488

    
489
int AUD_get_live (void)
490
{
491
    return live;
492
}
493

    
494
int AUD_get_buffer_size (void)
495
{
496
    return bufsize;
497
}
498

    
499
void AUD_init (void)
500
{
501
    int fsp;
502
    int _fragsize = 4096;
503

    
504
    DEREF (pab);
505

    
506
    fsp = _fragsize;
507
    if (0 != (fsp & (fsp - 1))) {
508
        Fail ("fragment size %d is not power of 2", fsp);
509
    }
510

    
511
    conf_fragsize = lsbindex (fsp);
512
}