VirtualBox

Changeset 7333 in vbox


Ignore:
Timestamp:
Mar 6, 2008 4:29:34 PM (17 years ago)
Author:
vboxsync
Message:

solaudio: some fixes.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Audio/solaudio.c

    r6000 r7333  
    2626#include <sys/fcntl.h>
    2727#include <sys/stat.h>
    28 #include <sys/mman.h>
     28#include <sys/time.h>
    2929
    3030#define LOG_GROUP LOG_GROUP_DEV_AUDIO
     
    4545typedef struct solaudioVoiceOut {
    4646    HWVoiceOut hw;
    47     int fd;
    48     int ctl_fd;
    49     int buffers_played;
    50     void *pcm_buf;
     47    int        AudioDev;
     48    int        AudioCtl;
     49    int        cBuffersPlayed;
     50    void      *pPCMBuf;
    5151} solaudioVoiceOut;
    5252
     
    6161} conf =
    6262{
    63     INIT_FIELD (buffer_size =) 4096,
     63    INIT_FIELD (buffer_size =) 8192,
    6464    INIT_FIELD (nbuffers =) 4,
    6565};
     66
    6667
    6768static void GCC_FMT_ATTR (2, 3) solaudio_logerr (int err, const char *fmt, ...)
     
    118119}
    119120
     121
    120122static int solaudio_open (int in, audio_info_t *info, int *pfd, int *pctl_fd)
    121123{
     
    127129    audio_info_t audInfo;
    128130
    129     /* @todo add Log for failures. Use AUDIO_GETDEV instead of hardcoding /dev/audio */
     131    /* @todo Use AUDIO_GETDEV instead of hardcoding /dev/audio */
    130132    if (stat(deviceName, &st) < 0)
    131         return -1;
     133    {
     134        LogRel(("solaudio: failed to stat %s\n", deviceName));
     135        return -1;
     136    }
    132137
    133138    if (!S_ISCHR(st.st_mode))
    134         return -1;
     139    {
     140        LogRel(("solaudio: invalid mode for %s\n", deviceName));
     141        return -1;
     142    }
    135143
    136144    fd = open(deviceName, O_WRONLY | O_NONBLOCK);
    137145    if (fd < 0)
    138         return -1;
     146    {
     147        LogRel(("solaudio: failed to open %s\n", deviceName));
     148        return -1;
     149    }
    139150
    140151    ctl_fd = open(ctlDeviceName, O_WRONLY | O_NONBLOCK);
    141152    if (ctl_fd < 0)
    142153    {
     154        LogRel(("solaudio: failed to open %s\n", ctlDeviceName));
    143155        close(fd);
    144156        return -1;
     
    190202
    191203    if (solaudio_open(0, &audioInfo, &fd, &ctl_fd))
    192         return -1;
    193 
    194     sol->fd = fd;
    195     sol->ctl_fd = ctl_fd;
     204    {
     205        LogRel(("solaudio: solaudio_open failed\n"));
     206        return -1;
     207    }
     208
     209    sol->AudioDev = fd;
     210    sol->AudioCtl = ctl_fd;
    196211    obt_as.freq = audioInfo.play.sample_rate;
    197212    obt_as.nchannels = audioInfo.play.channels;
     
    200215
    201216    audio_pcm_init_info (&hw->info, &obt_as);
    202     sol->buffers_played = audioInfo.play.eof;
    203 
    204     hw->samples = audioInfo.play.buffer_size / 2;
    205     sol->pcm_buf = RTMemAllocZ(hw->samples << hw->info.shift);
    206     if (!sol->pcm_buf)
    207     {
    208         LogRel(("solaudio: failed to alloc %d %d bytes to pcm_buf\n", hw->samples << hw->info.shift, hw->samples));
     217    sol->cBuffersPlayed = audioInfo.play.eof;
     218
     219    hw->samples = audioInfo.play.buffer_size >> hw->info.shift;
     220    sol->pPCMBuf = RTMemAllocZ(audioInfo.play.buffer_size);
     221    if (!sol->pPCMBuf)
     222    {
     223        LogRel(("solaudio: failed to alloc %d %d bytes to pPCMBuf\n", hw->samples << hw->info.shift, hw->samples));
    209224        return -1;
    210225    }
     
    213228}
    214229
     230
    215231static void solaudio_stop (solaudioVoiceOut *solvw)
    216232{
    217233    LogFlow(("solaudio: stop\n"));
    218     if (solvw->fd < 0 || solvw->ctl_fd < 0)
     234    if (solvw->AudioDev < 0 || solvw->AudioCtl < 0)
     235    {
     236        Log(("solaudio: invalid file descriptors\n"));
    219237        return;
    220 
    221     if (ioctl(solvw->ctl_fd, I_SETSIG, 0) < 0)
     238    }
     239
     240    if (ioctl(solvw->AudioCtl, I_SETSIG, 0) < 0)
     241    {
     242        LogRel(("solaudio: failed to stop signalling\n"));
    222243        return;
    223 
    224     if (ioctl(solvw->fd, I_FLUSH, FLUSHW) < 0)
     244    }
     245
     246    if (ioctl(solvw->AudioDev, I_FLUSH, FLUSHW) < 0)
     247    {
     248        Log(("solaudio: failed to drop unplayed buffers\n"));
    225249        return;
    226 
    227     close(solvw->fd);
    228     solvw->fd = -1;
    229     close(solvw->ctl_fd);
    230     solvw->ctl_fd = -1;
    231     solvw->buffers_played = 0;
    232     if (solvw->pcm_buf)
    233     {
    234         RTMemFree(solvw->pcm_buf);
    235         solvw->pcm_buf = NULL;
    236     }
    237 }
     250    }
     251
     252    close(solvw->AudioDev);
     253    solvw->AudioDev = -1;
     254    close(solvw->AudioCtl);
     255    solvw->AudioCtl = -1;
     256    solvw->cBuffersPlayed = 0;
     257    if (solvw->pPCMBuf)
     258    {
     259        RTMemFree(solvw->pPCMBuf);
     260        solvw->pPCMBuf = NULL;
     261    }
     262}
     263
    238264
    239265static void solaudio_fini_out (HWVoiceOut *hw)
     
    241267    solaudioVoiceOut *sol = (solaudioVoiceOut *) hw;
    242268    solaudio_stop (sol);
    243     LogFlow(("solaudio: fini_out done.\n"));
     269    LogFlow(("solaudio: fini_out done\n"));
    244270}
    245271
     
    248274{
    249275    audio_info_t audioInfo;
    250     int buffers;
     276    int buffers = 0;
    251277
    252278    AUDIO_INITINFO(&audioInfo);
    253     if (ioctl(solvw->fd, AUDIO_GETINFO, &audioInfo) < 0)
    254         return -1;
    255 
    256     buffers = audioInfo.play.buffer_size * (2 + audioInfo.play.eof - solvw->buffers_played);
     279    if (ioctl(solvw->AudioDev, AUDIO_GETINFO, &audioInfo) < 0)
     280    {
     281        Log(("solaudio: AUDIO_GETINFO ioctl failed\n"));
     282        return -1;
     283    }
     284
     285    buffers = audioInfo.play.buffer_size * (2 + audioInfo.play.eof - solvw->cBuffersPlayed);
    257286
    258287    LogFlow(("avail: eof=%d samples=%d bufsize=%d bufplayed=%d avail=%d\n", audioInfo.play.eof, audioInfo.play.samples,
    259         audioInfo.play.buffer_size, solvw->buffers_played, buffers));
     288        audioInfo.play.buffer_size, solvw->cBuffersPlayed, buffers));
    260289    return buffers;
    261290}
    262291
     292static void solaudio_yield (solaudioVoiceOut *pSol)
     293{
     294    audio_info_t AudioInfo;
     295    timespec_t WaitTimeSpec;
     296    if (ioctl (pSol->AudioDev, AUDIO_GETINFO, &AudioInfo) < 0)
     297        return;
     298
     299    WaitTimeSpec.tv_sec = 0;
     300    WaitTimeSpec.tv_nsec = 10000000;
     301
     302    while (AudioInfo.play.eof < pSol->cBuffersPlayed - 2)
     303    {
     304        nanosleep(&WaitTimeSpec, NULL);
     305        if (ioctl(pSol->AudioDev, AUDIO_GETINFO, &AudioInfo) < 0)
     306            break;
     307    }
     308}
     309
     310
    263311static int solaudio_run_out (HWVoiceOut *hw)
    264312{
    265     solaudioVoiceOut *sol = (solaudioVoiceOut *) hw;
    266     int live, samples, rpos, decr, avail;
    267     uint16_t *dst = NULL;
    268     st_sample_t *src;
    269 
    270     live = audio_pcm_hw_get_live_out (hw);
    271     if (!live)
     313    solaudioVoiceOut *pSol = (solaudioVoiceOut *) hw;
     314    int          csLive, csDecr, csSamples, csToWrite, csAvail;
     315    size_t       cbAvail, cbToWrite, cbWritten;
     316    uint8_t     *pu8Dst;
     317    st_sample_t *psSrc;
     318
     319    csLive = audio_pcm_hw_get_live_out (hw);
     320    if (!csLive)
    272321        return 0;
    273322
    274     avail = solaudio_availbuf(sol);
    275     if (avail <= 0)
    276         return 0;
    277 
    278     decr = audio_MIN(live, avail);
    279     samples = decr;
    280     rpos = hw->rpos;
    281     LogFlow(("solaudio: run_out: samples=%d live=%d avail=%d\n", samples, live, avail));
    282     while (samples)
    283     {
    284         int left_till_end_samples = hw->samples - rpos;
    285         int convert_samples = audio_MIN (samples, left_till_end_samples);
    286         int written = 0;
    287 
    288         src = hw->mix_buf + rpos;
    289         dst = advance (sol->pcm_buf, rpos << hw->info.shift);
    290         hw->clip (dst, src, convert_samples << hw->info.shift);
    291 
    292         written = write(sol->fd, (char *)dst, convert_samples << hw->info.shift);
    293         if (written == -1)
    294         {
    295             LogRel(("solaudio: Write error!\n"));
    296             decr = 0;
    297             break;
    298         }
    299 
    300         if (written != convert_samples << hw->info.shift)
    301         {
    302             int wsamples = written >> hw->info.shift;
    303             int wbytes = wsamples << hw->info.shift;
    304             if (wbytes != written)
    305                 LogRel(("solaudio: Misaligned write %d (requested %d) alignment %d\n", wbytes, written, hw->info.align + 1));
    306 
    307             decr -= wsamples;
    308             rpos = (rpos + wsamples) % hw->samples;
    309             LogFlow(("solaudio: Partial write=%d expected=%d\n", written, convert_samples << hw->info.shift));
    310             break;
    311         }
    312 
    313         rpos = (rpos + convert_samples) % hw->samples;
    314         samples -= convert_samples;
    315 
    316         sol->buffers_played++;
    317         write(sol->fd, NULL, 0);    /* Increment audio eof marker. */
    318         LogFlow(("solaudio: samples=%d written=%d\n", samples, written));
    319     }
    320 
    321     LogFlow(("solaudio: run_out: decr=%d\n", decr));
    322     hw->rpos = rpos;
    323     return decr;
    324 }
     323    for (;;)
     324    {
     325        cbAvail = solaudio_availbuf (pSol);
     326        if (cbAvail > 0)
     327            break;
     328        solaudio_yield(pSol);
     329    }
     330
     331    csAvail   = cbAvail >> hw->info.shift; /* bytes => samples */
     332    csDecr    = audio_MIN (csLive, csAvail);
     333    csSamples = csDecr;
     334
     335    while (csSamples)
     336    {
     337        /* split request at the end of our samples buffer */
     338        csToWrite = audio_MIN (csSamples, hw->samples - hw->rpos);
     339        cbToWrite = csToWrite << hw->info.shift;
     340        psSrc     = hw->mix_buf + hw->rpos;
     341        pu8Dst    = advance (pSol->pPCMBuf, hw->rpos << hw->info.shift);
     342
     343        hw->clip (pu8Dst, psSrc, csToWrite);
     344
     345        cbWritten = write (pSol->AudioDev, pu8Dst, cbToWrite);
     346        if (cbWritten < 0)
     347            break;
     348
     349        hw->rpos   = (hw->rpos + csToWrite) % hw->samples;
     350        csSamples -= csToWrite;
     351    }
     352    /* Increment eof marker for synchronous buffer processed */
     353    write (pSol->AudioDev, NULL, 0);
     354    pSol->cBuffersPlayed++;
     355    return csDecr;
     356}
     357
    325358
    326359static int solaudio_ctl_out (HWVoiceOut *hw, int cmd, ...)
     
    334367            audio_info_t audioInfo;
    335368            AUDIO_INITINFO(&audioInfo);
    336             ioctl(sol->fd, AUDIO_GETINFO, &audioInfo);
     369            ioctl(sol->AudioDev, AUDIO_GETINFO, &audioInfo);
    337370            audioInfo.play.eof = 0;
    338371            audioInfo.play.samples = 0;
    339             ioctl(sol->fd, AUDIO_SETINFO, &audioInfo);
    340 
    341             sol->buffers_played = 0;
    342             audio_pcm_info_clear_buf (&hw->info, sol->pcm_buf, hw->samples);
     372            ioctl(sol->AudioDev, AUDIO_SETINFO, &audioInfo);
     373
     374            sol->cBuffersPlayed = 0;
     375            audio_pcm_info_clear_buf (&hw->info, sol->pPCMBuf, hw->samples);
    343376            LogFlow(("solaudio: voice_enable\n"));
    344377            break;
     
    361394}
    362395
     396
    363397static void *solaudio_audio_init (void)
    364398{
     
    366400}
    367401
     402
    368403static void solaudio_audio_fini (void *opaque)
    369404{
    370405    (void) opaque;
    371406}
     407
    372408
    373409static struct audio_pcm_ops solaudio_pcm_ops = {
     
    384420    NULL
    385421};
    386 
    387422
    388423static struct audio_option solaudio_options[] = {
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette