Annotation of qemu/audio/audio.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * QEMU Audio subsystem
                      3:  * 
                      4:  * Copyright (c) 2003-2004 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 <assert.h>
                     25: #include "vl.h"
                     26: 
                     27: #define USE_WAV_AUDIO
                     28: 
                     29: #include "audio/audio_int.h"
                     30: 
                     31: #define dolog(...) AUD_log ("audio", __VA_ARGS__)
                     32: #ifdef DEBUG
                     33: #define ldebug(...) dolog (__VA_ARGS__)
                     34: #else
                     35: #define ldebug(...)
                     36: #endif
                     37: 
                     38: #define QC_AUDIO_DRV    "QEMU_AUDIO_DRV"
                     39: #define QC_VOICES       "QEMU_VOICES"
                     40: #define QC_FIXED_FORMAT "QEMU_FIXED_FORMAT"
                     41: #define QC_FIXED_FREQ   "QEMU_FIXED_FREQ"
                     42: 
                     43: static HWVoice *hw_voices;
                     44: 
                     45: AudioState audio_state = {
                     46:     1,                          /* use fixed settings */
                     47:     44100,                      /* fixed frequency */
                     48:     2,                          /* fixed channels */
                     49:     AUD_FMT_S16,                /* fixed format */
                     50:     1,                          /* number of hw voices */
                     51:     -1                          /* voice size */
                     52: };
                     53: 
                     54: /* http://www.df.lth.se/~john_e/gems/gem002d.html */
                     55: /* http://www.multi-platforms.com/Tips/PopCount.htm */
                     56: uint32_t popcount (uint32_t u)
                     57: {
                     58:     u = ((u&0x55555555) + ((u>>1)&0x55555555));
                     59:     u = ((u&0x33333333) + ((u>>2)&0x33333333));
                     60:     u = ((u&0x0f0f0f0f) + ((u>>4)&0x0f0f0f0f));
                     61:     u = ((u&0x00ff00ff) + ((u>>8)&0x00ff00ff));
                     62:     u = ( u&0x0000ffff) + (u>>16);
                     63:     return u;
                     64: }
                     65: 
                     66: inline uint32_t lsbindex (uint32_t u)
                     67: {
                     68:     return popcount ((u&-u)-1);
                     69: }
                     70: 
                     71: int audio_get_conf_int (const char *key, int defval)
                     72: {
                     73:     int val = defval;
                     74:     char *strval;
                     75: 
                     76:     strval = getenv (key);
                     77:     if (strval) {
                     78:         val = atoi (strval);
                     79:     }
                     80: 
                     81:     return val;
                     82: }
                     83: 
                     84: const char *audio_get_conf_str (const char *key, const char *defval)
                     85: {
                     86:     const char *val = getenv (key);
                     87:     if (!val)
                     88:         return defval;
                     89:     else
                     90:         return val;
                     91: }
                     92: 
                     93: void AUD_log (const char *cap, const char *fmt, ...)
                     94: {
                     95:     va_list ap;
                     96:     fprintf (stderr, "%s: ", cap);
                     97:     va_start (ap, fmt);
                     98:     vfprintf (stderr, fmt, ap);
                     99:     va_end (ap);
                    100: }
                    101: 
                    102: /*
                    103:  * Soft Voice
                    104:  */
                    105: void pcm_sw_free_resources (SWVoice *sw)
                    106: {
                    107:     if (sw->buf) qemu_free (sw->buf);
                    108:     if (sw->rate) st_rate_stop (sw->rate);
                    109:     sw->buf = NULL;
                    110:     sw->rate = NULL;
                    111: }
                    112: 
                    113: int pcm_sw_alloc_resources (SWVoice *sw)
                    114: {
                    115:     sw->buf = qemu_mallocz (sw->hw->samples * sizeof (st_sample_t));
                    116:     if (!sw->buf)
                    117:         return -1;
                    118: 
                    119:     sw->rate = st_rate_start (sw->freq, sw->hw->freq);
                    120:     if (!sw->rate) {
                    121:         qemu_free (sw->buf);
                    122:         sw->buf = NULL;
                    123:         return -1;
                    124:     }
                    125:     return 0;
                    126: }
                    127: 
                    128: void pcm_sw_fini (SWVoice *sw)
                    129: {
                    130:     pcm_sw_free_resources (sw);
                    131: }
                    132: 
                    133: int pcm_sw_init (SWVoice *sw, HWVoice *hw, int freq,
                    134:                  int nchannels, audfmt_e fmt)
                    135: {
                    136:     int bits = 8, sign = 0;
                    137: 
                    138:     switch (fmt) {
                    139:     case AUD_FMT_S8:
                    140:         sign = 1;
                    141:     case AUD_FMT_U8:
                    142:         break;
                    143: 
                    144:     case AUD_FMT_S16:
                    145:         sign = 1;
                    146:     case AUD_FMT_U16:
                    147:         bits = 16;
                    148:         break;
                    149:     }
                    150: 
                    151:     sw->hw = hw;
                    152:     sw->freq = freq;
                    153:     sw->fmt = fmt;
                    154:     sw->nchannels = nchannels;
                    155:     sw->shift = (nchannels == 2) + (bits == 16);
                    156:     sw->align = (1 << sw->shift) - 1;
                    157:     sw->left = 0;
                    158:     sw->pos = 0;
                    159:     sw->wpos = 0;
                    160:     sw->live = 0;
                    161:     sw->ratio = (sw->hw->freq * ((int64_t) INT_MAX)) / sw->freq;
                    162:     sw->bytes_per_second = sw->freq << sw->shift;
                    163:     sw->conv = mixeng_conv[nchannels == 2][sign][bits == 16];
                    164: 
                    165:     pcm_sw_free_resources (sw);
                    166:     return pcm_sw_alloc_resources (sw);
                    167: }
                    168: 
                    169: /* Hard voice */
                    170: void pcm_hw_free_resources (HWVoice *hw)
                    171: {
                    172:     if (hw->mix_buf)
                    173:         qemu_free (hw->mix_buf);
                    174:     hw->mix_buf = NULL;
                    175: }
                    176: 
                    177: int pcm_hw_alloc_resources (HWVoice *hw)
                    178: {
                    179:     hw->mix_buf = qemu_mallocz (hw->samples * sizeof (st_sample_t));
                    180:     if (!hw->mix_buf)
                    181:         return -1;
                    182:     return 0;
                    183: }
                    184: 
                    185: void pcm_hw_fini (HWVoice *hw)
                    186: {
                    187:     if (hw->active) {
                    188:         ldebug ("pcm_hw_fini: %d %d %d\n", hw->freq, hw->nchannels, hw->fmt);
                    189:         pcm_hw_free_resources (hw);
                    190:         hw->pcm_ops->fini (hw);
                    191:         memset (hw, 0, audio_state.drv->voice_size);
                    192:     }
                    193: }
                    194: 
                    195: void pcm_hw_gc (HWVoice *hw)
                    196: {
                    197:     if (hw->nb_voices)
                    198:         return;
                    199: 
                    200:     pcm_hw_fini (hw);
                    201: }
                    202: 
                    203: int pcm_hw_get_live (HWVoice *hw)
                    204: {
                    205:     int i, alive = 0, live = hw->samples;
                    206: 
                    207:     for (i = 0; i < hw->nb_voices; i++) {
                    208:         if (hw->pvoice[i]->live) {
                    209:             live = audio_MIN (hw->pvoice[i]->live, live);
                    210:             alive += 1;
                    211:         }
                    212:     }
                    213: 
                    214:     if (alive)
                    215:         return live;
                    216:     else
                    217:         return -1;
                    218: }
                    219: 
                    220: int pcm_hw_get_live2 (HWVoice *hw, int *nb_active)
                    221: {
                    222:     int i, alive = 0, live = hw->samples;
                    223: 
                    224:     *nb_active = 0;
                    225:     for (i = 0; i < hw->nb_voices; i++) {
                    226:         if (hw->pvoice[i]->live) {
                    227:             if (hw->pvoice[i]->live < live) {
                    228:                 *nb_active = hw->pvoice[i]->active != 0;
                    229:                 live = hw->pvoice[i]->live;
                    230:             }
                    231:             alive += 1;
                    232:         }
                    233:     }
                    234: 
                    235:     if (alive)
                    236:         return live;
                    237:     else
                    238:         return -1;
                    239: }
                    240: 
                    241: void pcm_hw_dec_live (HWVoice *hw, int decr)
                    242: {
                    243:     int i;
                    244: 
                    245:     for (i = 0; i < hw->nb_voices; i++) {
                    246:         if (hw->pvoice[i]->live) {
                    247:             hw->pvoice[i]->live -= decr;
                    248:         }
                    249:     }
                    250: }
                    251: 
                    252: void pcm_hw_clear (HWVoice *hw, void *buf, int len)
                    253: {
                    254:     if (!len)
                    255:         return;
                    256: 
                    257:     switch (hw->fmt) {
                    258:     case AUD_FMT_S16:
                    259:     case AUD_FMT_S8:
                    260:         memset (buf, len << hw->shift, 0x00);
                    261:         break;
                    262: 
                    263:     case AUD_FMT_U8:
                    264:         memset (buf, len << hw->shift, 0x80);
                    265:         break;
                    266: 
                    267:     case AUD_FMT_U16:
                    268:         {
                    269:             unsigned int i;
                    270:             uint16_t *p = buf;
                    271:             int shift = hw->nchannels - 1;
                    272: 
                    273:             for (i = 0; i < len << shift; i++) {
                    274:                 p[i] = INT16_MAX;
                    275:             }
                    276:         }
                    277:         break;
                    278:     }
                    279: }
                    280: 
                    281: int pcm_hw_write (SWVoice *sw, void *buf, int size)
                    282: {
                    283:     int hwsamples, samples, isamp, osamp, wpos, live, dead, left, swlim, blck;
                    284:     int ret = 0, pos = 0;
                    285:     if (!sw)
                    286:         return size;
                    287: 
                    288:     hwsamples = sw->hw->samples;
                    289:     samples = size >> sw->shift;
                    290: 
                    291:     if (!sw->live) {
                    292:         sw->wpos = sw->hw->rpos;
                    293:     }
                    294:     wpos = sw->wpos;
                    295:     live = sw->live;
                    296:     dead = hwsamples - live;
                    297:     swlim = (dead * ((int64_t) INT_MAX)) / sw->ratio;
                    298:     swlim = audio_MIN (swlim, samples);
                    299: 
                    300:     ldebug ("size=%d live=%d dead=%d swlim=%d wpos=%d\n",
                    301:            size, live, dead, swlim, wpos);
                    302:     if (swlim)
                    303:         sw->conv (sw->buf, buf, swlim);
                    304: 
                    305:     while (swlim) {
                    306:         dead = hwsamples - live;
                    307:         left = hwsamples - wpos;
                    308:         blck = audio_MIN (dead, left);
                    309:         if (!blck) {
                    310:             /* dolog ("swlim=%d\n", swlim); */
                    311:             break;
                    312:         }
                    313:         isamp = swlim;
                    314:         osamp = blck;
                    315:         st_rate_flow (sw->rate, sw->buf + pos, sw->hw->mix_buf + wpos, &isamp, &osamp);
                    316:         ret += isamp;
                    317:         swlim -= isamp;
                    318:         pos += isamp;
                    319:         live += osamp;
                    320:         wpos = (wpos + osamp) % hwsamples;
                    321:     }
                    322: 
                    323:     sw->wpos = wpos;
                    324:     sw->live = live;
                    325:     return ret << sw->shift;
                    326: }
                    327: 
                    328: int pcm_hw_init (HWVoice *hw, int freq, int nchannels, audfmt_e fmt)
                    329: {
                    330:     int sign = 0, bits = 8;
                    331: 
                    332:     pcm_hw_fini (hw);
                    333:     ldebug ("pcm_hw_init: %d %d %d\n", freq, nchannels, fmt);
                    334:     if (hw->pcm_ops->init (hw, freq, nchannels, fmt)) {
                    335:         memset (hw, 0, audio_state.drv->voice_size);
                    336:         return -1;
                    337:     }
                    338: 
                    339:     switch (hw->fmt) {
                    340:     case AUD_FMT_S8:
                    341:         sign = 1;
                    342:     case AUD_FMT_U8:
                    343:         break;
                    344: 
                    345:     case AUD_FMT_S16:
                    346:         sign = 1;
                    347:     case AUD_FMT_U16:
                    348:         bits = 16;
                    349:         break;
                    350:     }
                    351: 
                    352:     hw->nb_voices = 0;
                    353:     hw->active = 1;
                    354:     hw->shift = (hw->nchannels == 2) + (bits == 16);
                    355:     hw->bytes_per_second = hw->freq << hw->shift;
                    356:     hw->align = (1 << hw->shift) - 1;
                    357:     hw->samples = hw->bufsize >> hw->shift;
                    358:     hw->clip = mixeng_clip[hw->nchannels == 2][sign][bits == 16];
                    359:     if (pcm_hw_alloc_resources (hw)) {
                    360:         pcm_hw_fini (hw);
                    361:         return -1;
                    362:     }
                    363:     return 0;
                    364: }
                    365: 
                    366: static int dist (void *hw)
                    367: {
                    368:     if (hw) {
                    369:         return (((uint8_t *) hw - (uint8_t *) hw_voices)
                    370:                 / audio_state.drv->voice_size) + 1;
                    371:     }
                    372:     else {
                    373:         return 0;
                    374:     }
                    375: }
                    376: 
                    377: #define ADVANCE(hw) \
                    378:     ((hw) ? advance (hw, audio_state.drv->voice_size) : hw_voices)
                    379: 
                    380: HWVoice *pcm_hw_find_any (HWVoice *hw)
                    381: {
                    382:     int i = dist (hw);
                    383:     for (; i < audio_state.nb_hw_voices; i++) {
                    384:         hw = ADVANCE (hw);
                    385:         return hw;
                    386:     }
                    387:     return NULL;
                    388: }
                    389: 
                    390: HWVoice *pcm_hw_find_any_active (HWVoice *hw)
                    391: {
                    392:     int i = dist (hw);
                    393:     for (; i < audio_state.nb_hw_voices; i++) {
                    394:         hw = ADVANCE (hw);
                    395:         if (hw->active)
                    396:             return hw;
                    397:     }
                    398:     return NULL;
                    399: }
                    400: 
                    401: HWVoice *pcm_hw_find_any_active_enabled (HWVoice *hw)
                    402: {
                    403:     int i = dist (hw);
                    404:     for (; i < audio_state.nb_hw_voices; i++) {
                    405:         hw = ADVANCE (hw);
                    406:         if (hw->active && hw->enabled)
                    407:             return hw;
                    408:     }
                    409:     return NULL;
                    410: }
                    411: 
                    412: HWVoice *pcm_hw_find_any_passive (HWVoice *hw)
                    413: {
                    414:     int i = dist (hw);
                    415:     for (; i < audio_state.nb_hw_voices; i++) {
                    416:         hw = ADVANCE (hw);
                    417:         if (!hw->active)
                    418:             return hw;
                    419:     }
                    420:     return NULL;
                    421: }
                    422: 
                    423: HWVoice *pcm_hw_find_specific (HWVoice *hw, int freq,
                    424:                                int nchannels, audfmt_e fmt)
                    425: {
                    426:     while ((hw = pcm_hw_find_any_active (hw))) {
                    427:         if (hw->freq == freq &&
                    428:             hw->nchannels == nchannels &&
                    429:             hw->fmt == fmt)
                    430:             return hw;
                    431:     }
                    432:     return NULL;
                    433: }
                    434: 
                    435: HWVoice *pcm_hw_add (int freq, int nchannels, audfmt_e fmt)
                    436: {
                    437:     HWVoice *hw;
                    438: 
                    439:     if (audio_state.fixed_format) {
                    440:         freq = audio_state.fixed_freq;
                    441:         nchannels = audio_state.fixed_channels;
                    442:         fmt = audio_state.fixed_fmt;
                    443:     }
                    444: 
                    445:     hw = pcm_hw_find_specific (NULL, freq, nchannels, fmt);
                    446: 
                    447:     if (hw)
                    448:         return hw;
                    449: 
                    450:     hw = pcm_hw_find_any_passive (NULL);
                    451:     if (hw) {
                    452:         hw->pcm_ops = audio_state.drv->pcm_ops;
                    453:         if (!hw->pcm_ops)
                    454:             return NULL;
                    455: 
                    456:         if (pcm_hw_init (hw, freq, nchannels, fmt)) {
                    457:             pcm_hw_gc (hw);
                    458:             return NULL;
                    459:         }
                    460:         else
                    461:             return hw;
                    462:     }
                    463: 
                    464:     return pcm_hw_find_any (NULL);
                    465: }
                    466: 
                    467: int pcm_hw_add_sw (HWVoice *hw, SWVoice *sw)
                    468: {
                    469:     SWVoice **pvoice = qemu_mallocz ((hw->nb_voices + 1) * sizeof (sw));
                    470:     if (!pvoice)
                    471:         return -1;
                    472: 
                    473:     memcpy (pvoice, hw->pvoice, hw->nb_voices * sizeof (sw));
                    474:     qemu_free (hw->pvoice);
                    475:     hw->pvoice = pvoice;
                    476:     hw->pvoice[hw->nb_voices++] = sw;
                    477:     return 0;
                    478: }
                    479: 
                    480: int pcm_hw_del_sw (HWVoice *hw, SWVoice *sw)
                    481: {
                    482:     int i, j;
                    483:     if (hw->nb_voices > 1) {
                    484:         SWVoice **pvoice = qemu_mallocz ((hw->nb_voices - 1) * sizeof (sw));
                    485: 
                    486:         if (!pvoice) {
                    487:             dolog ("Can not maintain consistent state (not enough memory)\n");
                    488:             return -1;
                    489:         }
                    490: 
                    491:         for (i = 0, j = 0; i < hw->nb_voices; i++) {
                    492:             if (j >= hw->nb_voices - 1) {
                    493:                 dolog ("Can not maintain consistent state "
                    494:                        "(invariant violated)\n");
                    495:                 return -1;
                    496:             }
                    497:             if (hw->pvoice[i] != sw)
                    498:                 pvoice[j++] = hw->pvoice[i];
                    499:         }
                    500:         qemu_free (hw->pvoice);
                    501:         hw->pvoice = pvoice;
                    502:         hw->nb_voices -= 1;
                    503:     }
                    504:     else {
                    505:         qemu_free (hw->pvoice);
                    506:         hw->pvoice = NULL;
                    507:         hw->nb_voices = 0;
                    508:     }
                    509:     return 0;
                    510: }
                    511: 
                    512: SWVoice *pcm_create_voice_pair (int freq, int nchannels, audfmt_e fmt)
                    513: {
                    514:     SWVoice *sw;
                    515:     HWVoice *hw;
                    516: 
                    517:     sw = qemu_mallocz (sizeof (*sw));
                    518:     if (!sw)
                    519:         goto err1;
                    520: 
                    521:     hw = pcm_hw_add (freq, nchannels, fmt);
                    522:     if (!hw)
                    523:         goto err2;
                    524: 
                    525:     if (pcm_hw_add_sw (hw, sw))
                    526:         goto err3;
                    527: 
                    528:     if (pcm_sw_init (sw, hw, freq, nchannels, fmt))
                    529:         goto err4;
                    530: 
                    531:     return sw;
                    532: 
                    533: err4:
                    534:     pcm_hw_del_sw (hw, sw);
                    535: err3:
                    536:     pcm_hw_gc (hw);
                    537: err2:
                    538:     qemu_free (sw);
                    539: err1:
                    540:     return NULL;
                    541: }
                    542: 
                    543: SWVoice *AUD_open (SWVoice *sw, const char *name,
                    544:                    int freq, int nchannels, audfmt_e fmt)
                    545: {
                    546:     if (!audio_state.drv) {
                    547:         return NULL;
                    548:     }
                    549: 
                    550:     if (sw && freq == sw->freq && sw->nchannels == nchannels && sw->fmt == fmt) {
                    551:         return sw;
                    552:     }
                    553: 
                    554:     if (sw) {
                    555:         ldebug ("Different format %s %d %d %d\n",
                    556:                 name,
                    557:                 sw->freq == freq,
                    558:                 sw->nchannels == nchannels,
                    559:                 sw->fmt == fmt);
                    560:     }
                    561: 
                    562:     if (nchannels != 1 && nchannels != 2) {
                    563:         dolog ("Bogus channel count %d for voice %s\n", nchannels, name);
                    564:         return NULL;
                    565:     }
                    566: 
                    567:     if (!audio_state.fixed_format && sw) {
                    568:         pcm_sw_fini (sw);
                    569:         pcm_hw_del_sw (sw->hw, sw);
                    570:         pcm_hw_gc (sw->hw);
                    571:         if (sw->name) {
                    572:             qemu_free (sw->name);
                    573:             sw->name = NULL;
                    574:         }
                    575:         qemu_free (sw);
                    576:         sw = NULL;
                    577:     }
                    578: 
                    579:     if (sw) {
                    580:         HWVoice *hw = sw->hw;
                    581:         if (!hw) {
                    582:             dolog ("Internal logic error voice %s has no hardware store\n",
                    583:                    name);
                    584:             return sw;
                    585:         }
                    586: 
                    587:         if (pcm_sw_init (sw, hw, freq, nchannels, fmt)) {
                    588:             pcm_sw_fini (sw);
                    589:             pcm_hw_del_sw (hw, sw);
                    590:             pcm_hw_gc (hw);
                    591:             if (sw->name) {
                    592:                 qemu_free (sw->name);
                    593:                 sw->name = NULL;
                    594:             }
                    595:             qemu_free (sw);
                    596:             return NULL;
                    597:         }
                    598:     }
                    599:     else {
                    600:         sw = pcm_create_voice_pair (freq, nchannels, fmt);
                    601:         if (!sw) {
                    602:             dolog ("Failed to create voice %s\n", name);
                    603:             return NULL;
                    604:         }
                    605:     }
                    606: 
                    607:     if (sw->name) {
                    608:         qemu_free (sw->name);
                    609:         sw->name = NULL;
                    610:     }
                    611:     sw->name = qemu_strdup (name);
                    612:     return sw;
                    613: }
                    614: 
                    615: void AUD_close (SWVoice *sw)
                    616: {
                    617:     if (!sw)
                    618:         return;
                    619: 
                    620:     pcm_sw_fini (sw);
                    621:     pcm_hw_del_sw (sw->hw, sw);
                    622:     pcm_hw_gc (sw->hw);
                    623:     if (sw->name) {
                    624:         qemu_free (sw->name);
                    625:         sw->name = NULL;
                    626:     }
                    627:     qemu_free (sw);
                    628: }
                    629: 
                    630: int AUD_write (SWVoice *sw, void *buf, int size)
                    631: {
                    632:     int bytes;
                    633: 
                    634:     if (!sw->hw->enabled)
                    635:         dolog ("Writing to disabled voice %s\n", sw->name);
                    636:     bytes = sw->hw->pcm_ops->write (sw, buf, size);
                    637:     return bytes;
                    638: }
                    639: 
                    640: void AUD_run (void)
                    641: {
                    642:     HWVoice *hw = NULL;
                    643: 
                    644:     while ((hw = pcm_hw_find_any_active_enabled (hw))) {
                    645:         int i;
                    646:         if (hw->pending_disable && pcm_hw_get_live (hw) <= 0) {
                    647:             hw->enabled = 0;
                    648:             hw->pcm_ops->ctl (hw, VOICE_DISABLE);
                    649:             for (i = 0; i < hw->nb_voices; i++) {
                    650:                 hw->pvoice[i]->live = 0;
                    651:                 /* hw->pvoice[i]->old_ticks = 0; */
                    652:             }
                    653:             continue;
                    654:         }
                    655: 
                    656:         hw->pcm_ops->run (hw);
                    657:         assert (hw->rpos < hw->samples);
                    658:         for (i = 0; i < hw->nb_voices; i++) {
                    659:             SWVoice *sw = hw->pvoice[i];
                    660:             if (!sw->active && !sw->live && sw->old_ticks) {
                    661:                 int64_t delta = qemu_get_clock (vm_clock) - sw->old_ticks;
                    662:                 if (delta > audio_state.ticks_threshold) {
                    663:                     ldebug ("resetting old_ticks for %s\n", sw->name);
                    664:                     sw->old_ticks = 0;
                    665:                 }
                    666:             }
                    667:         }
                    668:     }
                    669: }
                    670: 
                    671: int AUD_get_free (SWVoice *sw)
                    672: {
                    673:     int free;
                    674: 
                    675:     if (!sw)
                    676:         return 4096;
                    677: 
                    678:     free = ((sw->hw->samples - sw->live) << sw->hw->shift) * sw->ratio
                    679:         / INT_MAX;
                    680: 
                    681:     free &= ~sw->hw->align;
                    682:     if (!free) return 0;
                    683: 
                    684:     return free;
                    685: }
                    686: 
                    687: int AUD_get_buffer_size (SWVoice *sw)
                    688: {
                    689:     return sw->hw->bufsize;
                    690: }
                    691: 
                    692: void AUD_adjust (SWVoice *sw, int bytes)
                    693: {
                    694:     if (!sw)
                    695:         return;
                    696:     sw->old_ticks += (ticks_per_sec * (int64_t) bytes) / sw->bytes_per_second;
                    697: }
                    698: 
                    699: void AUD_reset (SWVoice *sw)
                    700: {
                    701:     sw->active = 0;
                    702:     sw->old_ticks = 0;
                    703: }
                    704: 
                    705: int AUD_calc_elapsed (SWVoice *sw)
                    706: {
                    707:     int64_t now, delta, bytes;
                    708:     int dead, swlim;
                    709: 
                    710:     if (!sw)
                    711:         return 0;
                    712: 
                    713:     now = qemu_get_clock (vm_clock);
                    714:     delta = now - sw->old_ticks;
                    715:     bytes = (delta * sw->bytes_per_second) / ticks_per_sec;
                    716:     if (delta < 0) {
                    717:         dolog ("whoops delta(<0)=%lld\n", delta);
                    718:         return 0;
                    719:     }
                    720: 
                    721:     dead = sw->hw->samples - sw->live;
                    722:     swlim = ((dead * (int64_t) INT_MAX) / sw->ratio);
                    723: 
                    724:     if (bytes > swlim) {
                    725:         return swlim;
                    726:     }
                    727:     else {
                    728:         return bytes;
                    729:     }
                    730: }
                    731: 
                    732: void AUD_enable (SWVoice *sw, int on)
                    733: {
                    734:     int i;
                    735:     HWVoice *hw;
                    736: 
                    737:     if (!sw)
                    738:         return;
                    739: 
                    740:     hw = sw->hw;
                    741:     if (on) {
                    742:         if (!sw->live)
                    743:             sw->wpos = sw->hw->rpos;
                    744:         if (!sw->old_ticks) {
                    745:             sw->old_ticks = qemu_get_clock (vm_clock);
                    746:         }
                    747:     }
                    748: 
                    749:     if (sw->active != on) {
                    750:         if (on) {
                    751:             hw->pending_disable = 0;
                    752:             if (!hw->enabled) {
                    753:                 hw->enabled = 1;
                    754:                 for (i = 0; i < hw->nb_voices; i++) {
                    755:                     ldebug ("resetting voice\n");
                    756:                     sw = hw->pvoice[i];
                    757:                     sw->old_ticks = qemu_get_clock (vm_clock);
                    758:                 }
                    759:                 hw->pcm_ops->ctl (hw, VOICE_ENABLE);
                    760:             }
                    761:         }
                    762:         else {
                    763:             if (hw->enabled && !hw->pending_disable) {
                    764:                 int nb_active = 0;
                    765:                 for (i = 0; i < hw->nb_voices; i++) {
                    766:                     nb_active += hw->pvoice[i]->active != 0;
                    767:                 }
                    768: 
                    769:                 if (nb_active == 1) {
                    770:                     hw->pending_disable = 1;
                    771:                 }
                    772:             }
                    773:         }
                    774:         sw->active = on;
                    775:     }
                    776: }
                    777: 
                    778: static struct audio_output_driver *drvtab[] = {
                    779: #ifdef CONFIG_OSS
                    780:     &oss_output_driver,
                    781: #endif
                    782: #ifdef CONFIG_FMOD
                    783:     &fmod_output_driver,
                    784: #endif
                    785: #ifdef CONFIG_SDL
                    786:     &sdl_output_driver,
                    787: #endif
                    788:     &no_output_driver,
                    789: #ifdef USE_WAV_AUDIO
                    790:     &wav_output_driver,
                    791: #endif
                    792: };
                    793: 
                    794: static int voice_init (struct audio_output_driver *drv)
                    795: {
                    796:     audio_state.opaque = drv->init ();
                    797:     if (audio_state.opaque) {
                    798:         if (audio_state.nb_hw_voices > drv->max_voices) {
                    799:             dolog ("`%s' does not support %d multiple hardware channels\n"
                    800:                    "Resetting to %d\n",
                    801:                    drv->name, audio_state.nb_hw_voices, drv->max_voices);
                    802:             audio_state.nb_hw_voices = drv->max_voices;
                    803:         }
                    804:         hw_voices = qemu_mallocz (audio_state.nb_hw_voices * drv->voice_size);
                    805:         if (hw_voices) {
                    806:             audio_state.drv = drv;
                    807:             return 1;
                    808:         }
                    809:         else {
                    810:             dolog ("Not enough memory for %d `%s' voices (each %d bytes)\n",
                    811:                    audio_state.nb_hw_voices, drv->name, drv->voice_size);
                    812:             drv->fini (audio_state.opaque);
                    813:             return 0;
                    814:         }
                    815:     }
                    816:     else {
                    817:         dolog ("Could not init `%s' audio\n", drv->name);
                    818:         return 0;
                    819:     }
                    820: }
                    821: 
                    822: static void audio_vm_stop_handler (void *opaque, int reason)
                    823: {
                    824:     HWVoice *hw = NULL;
                    825: 
                    826:     while ((hw = pcm_hw_find_any (hw))) {
                    827:         if (!hw->pcm_ops)
                    828:             continue;
                    829: 
                    830:         hw->pcm_ops->ctl (hw, reason ? VOICE_ENABLE : VOICE_DISABLE);
                    831:     }
                    832: }
                    833: 
                    834: static void audio_atexit (void)
                    835: {
                    836:     HWVoice *hw = NULL;
                    837: 
                    838:     while ((hw = pcm_hw_find_any (hw))) {
                    839:         if (!hw->pcm_ops)
                    840:             continue;
                    841: 
                    842:         hw->pcm_ops->ctl (hw, VOICE_DISABLE);
                    843:         hw->pcm_ops->fini (hw);
                    844:     }
                    845:     audio_state.drv->fini (audio_state.opaque);
                    846: }
                    847: 
                    848: static void audio_save (QEMUFile *f, void *opaque)
                    849: {
                    850: }
                    851: 
                    852: static int audio_load (QEMUFile *f, void *opaque, int version_id)
                    853: {
                    854:     if (version_id != 1)
                    855:         return -EINVAL;
                    856: 
                    857:     return 0;
                    858: }
                    859: 
                    860: void AUD_init (void)
                    861: {
                    862:     int i;
                    863:     int done = 0;
                    864:     const char *drvname;
                    865: 
                    866:     audio_state.fixed_format =
                    867:         !!audio_get_conf_int (QC_FIXED_FORMAT, audio_state.fixed_format);
                    868:     audio_state.fixed_freq =
                    869:         audio_get_conf_int (QC_FIXED_FREQ, audio_state.fixed_freq);
                    870:     audio_state.nb_hw_voices =
                    871:         audio_get_conf_int (QC_VOICES, audio_state.nb_hw_voices);
                    872: 
                    873:     if (audio_state.nb_hw_voices <= 0) {
                    874:         dolog ("Bogus number of voices %d, resetting to 1\n",
                    875:                audio_state.nb_hw_voices);
                    876:     }
                    877: 
                    878:     drvname = audio_get_conf_str (QC_AUDIO_DRV, NULL);
                    879:     if (drvname) {
                    880:         int found = 0;
                    881:         for (i = 0; i < sizeof (drvtab) / sizeof (drvtab[0]); i++) {
                    882:             if (!strcmp (drvname, drvtab[i]->name)) {
                    883:                 done = voice_init (drvtab[i]);
                    884:                 found = 1;
                    885:                 break;
                    886:             }
                    887:         }
                    888:         if (!found) {
                    889:             dolog ("Unknown audio driver `%s'\n", drvname);
                    890:         }
                    891:     }
                    892: 
                    893:     qemu_add_vm_stop_handler (audio_vm_stop_handler, NULL);
                    894:     atexit (audio_atexit);
                    895: 
                    896:     if (!done) {
                    897:         for (i = 0; !done && i < sizeof (drvtab) / sizeof (drvtab[0]); i++) {
                    898:             if (drvtab[i]->can_be_default)
                    899:                 done = voice_init (drvtab[i]);
                    900:         }
                    901:     }
                    902: 
                    903:     audio_state.ticks_threshold = ticks_per_sec / 50;
                    904:     audio_state.freq_threshold = 100;
                    905: 
                    906:     register_savevm ("audio", 0, 1, audio_save, audio_load, NULL);
                    907:     if (!done) {
                    908:         dolog ("Can not initialize audio subsystem\n");
                    909:         voice_init (&no_output_driver);
                    910:     }
                    911: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.