VirtualBox

Changeset 7454 in vbox


Ignore:
Timestamp:
Mar 14, 2008 10:00:39 AM (17 years ago)
Author:
vboxsync
Message:

Solaris host audio fixes. Now doesn't clip and proper timing.

File:
1 edited

Legend:

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

    r7333 r7454  
    2424#include <fcntl.h>
    2525#include <sys/audio.h>
    26 #include <sys/fcntl.h>
    2726#include <sys/stat.h>
    2827#include <sys/time.h>
     
    3029#define LOG_GROUP LOG_GROUP_DEV_AUDIO
    3130#include <VBox/log.h>
     31#include <iprt/env.h>
    3232
    3333#include "Builtins.h"
     
    3939#include "audio_int.h"
    4040
    41 
    4241/*******************************************************************************
    4342*   Structures and Typedefs                                                    *
    4443*******************************************************************************/
    4544typedef struct solaudioVoiceOut {
    46     HWVoiceOut hw;
     45    HWVoiceOut Hw;
    4746    int        AudioDev;
    4847    int        AudioCtl;
     
    5756struct
    5857{
    59     int buffer_size;
    60     int nbuffers;
     58    int cbBuffer;
    6159} conf =
    6260{
    63     INIT_FIELD (buffer_size =) 8192,
    64     INIT_FIELD (nbuffers =) 4,
     61    INIT_FIELD (cbBuffer =) 8912,
    6562};
    6663
     
    7067    va_list ap;
    7168
    72     va_start (ap, fmt);
    73     AUD_vlog (AUDIO_CAP, fmt, ap);
    74     va_end (ap);
    75 
    76     AUD_log (AUDIO_CAP, "Reason: %s\n", strerror (err));
     69    va_start(ap, fmt);
     70    AUD_vlog(AUDIO_CAP, fmt, ap);
     71    va_end(ap);
     72
     73    AUD_log(AUDIO_CAP, "Reason: %s\n", strerror(err));
    7774}
    7875
     
    111108
    112109        case AUDIO_PRECISION_16:
    113             return AUD_FMT_U16;
     110        {
     111            if (encoding == AUDIO_ENCODING_LINEAR)
     112                return AUD_FMT_S16;
     113            else
     114                return AUD_FMT_U16;
     115            break;
     116        }
    114117
    115118        default:
     
    120123
    121124
     125static char *solaudio_getdevice ()
     126{
     127    /* This is for multiple audio devices where env. var determines current one,
     128     * otherwise else we fallback to default.
     129     */
     130    char *pszAudioDev = RTEnvGet("AUDIODEV");
     131    if (pszAudioDev)
     132        return RTStrDup(pszAudioDev);
     133
     134    return RTStrDup("/dev/audio");
     135}
     136
     137
    122138static int solaudio_open (int in, audio_info_t *info, int *pfd, int *pctl_fd)
    123139{
    124     int fd;
    125     int ctl_fd;
    126     struct stat st;
    127     const char *deviceName = "/dev/audio";
    128     const char *ctlDeviceName = "/dev/audioctl";
    129     audio_info_t audInfo;
    130 
    131     /* @todo Use AUDIO_GETDEV instead of hardcoding /dev/audio */
    132     if (stat(deviceName, &st) < 0)
    133     {
    134         LogRel(("solaudio: failed to stat %s\n", deviceName));
    135         return -1;
    136     }
    137 
    138     if (!S_ISCHR(st.st_mode))
    139     {
    140         LogRel(("solaudio: invalid mode for %s\n", deviceName));
    141         return -1;
    142     }
    143 
    144     fd = open(deviceName, O_WRONLY | O_NONBLOCK);
    145     if (fd < 0)
    146     {
    147         LogRel(("solaudio: failed to open %s\n", deviceName));
    148         return -1;
    149     }
    150 
    151     ctl_fd = open(ctlDeviceName, O_WRONLY | O_NONBLOCK);
    152     if (ctl_fd < 0)
    153     {
    154         LogRel(("solaudio: failed to open %s\n", ctlDeviceName));
    155         close(fd);
    156         return -1;
    157     }
    158 
    159     AUDIO_INITINFO(&audInfo);
    160     if (ioctl(fd, AUDIO_GETINFO, &audInfo) < 0)
     140    int AudioDev;
     141    int AudioCtl;
     142    struct stat FileStat;
     143    const char *pszAudioDev = NULL;
     144    const char *pszAudioCtl = "/dev/audioctl";
     145    audio_info_t AudioInfo;
     146
     147    pszAudioDev = solaudio_getdevice();
     148    if (!pszAudioDev)
     149    {
     150        LogRel(("solaudio: solaudio_getdevice() failed to return a valid device.\n"));
     151        goto err;
     152    }
     153
     154    if (stat(pszAudioDev, &FileStat) < 0)
     155    {
     156        LogRel(("solaudio: failed to stat %s\n", pszAudioDev));
     157        goto err;
     158    }
     159
     160    if (!S_ISCHR(FileStat.st_mode))
     161    {
     162        LogRel(("solaudio: invalid mode for %s\n", pszAudioDev));
     163        goto err;
     164    }
     165
     166    AudioDev = open(pszAudioDev, O_WRONLY | O_NONBLOCK);
     167    if (AudioDev < 0)
     168    {
     169        LogRel(("solaudio: failed to open %s\n", pszAudioDev));
     170        goto err;
     171    }
     172
     173    AudioCtl = open(pszAudioCtl, O_WRONLY | O_NONBLOCK);
     174    if (AudioCtl < 0)
     175    {
     176        LogRel(("solaudio: failed to open %s\n", pszAudioCtl));
     177        close(AudioDev);
     178        goto err;
     179    }
     180
     181    AUDIO_INITINFO(&AudioInfo);
     182    if (ioctl(AudioDev, AUDIO_GETINFO, &AudioInfo) < 0)
    161183    {
    162184        LogRel(("solaudio: AUDIO_GETINFO failed\n"));
    163         close(fd);
    164         return -1;
    165     }
    166     audInfo.play.sample_rate = info->play.sample_rate;
    167     audInfo.play.channels = info->play.channels;
    168     audInfo.play.precision = info->play.precision;
    169     audInfo.play.encoding = info->play.encoding;
    170     audInfo.play.buffer_size = info->play.buffer_size;
    171     audInfo.play.gain = AUDIO_MID_GAIN;
    172     if (ioctl(fd, AUDIO_SETINFO, &audInfo) < 0)
     185        close(AudioDev);
     186        close(AudioCtl);
     187        goto err;
     188    }
     189    AudioInfo.play.sample_rate = info->play.sample_rate;
     190    AudioInfo.play.channels = info->play.channels;
     191    AudioInfo.play.precision = info->play.precision;
     192    AudioInfo.play.encoding = info->play.encoding;
     193    AudioInfo.play.buffer_size = info->play.buffer_size;
     194    AudioInfo.play.gain = AUDIO_MAX_GAIN;
     195    AudioInfo.play.balance = AUDIO_MID_BALANCE;
     196    if (ioctl(AudioDev, AUDIO_SETINFO, &AudioInfo) < 0)
    173197    {
    174198        LogRel(("solaudio: AUDIO_SETINFO failed\n"));
    175         close(fd);
    176         return -1;
    177     }
    178     LogFlow(("solaudio: system buffer_size=%d\n", audInfo.play.buffer_size));
    179     *pfd = fd;
    180     *pctl_fd = ctl_fd;
     199        close(AudioDev);
     200        close(AudioCtl);
     201        goto err;
     202    }
     203    LogFlow(("solaudio: buffer_size=%d\n", AudioInfo.play.buffer_size));
     204    *pfd = AudioDev;
     205    *pctl_fd = AudioCtl;
    181206    return 0;
     207
     208err:
     209    RTStrFree(pszAudioDev);
     210    return -1;
    182211}
    183212
     
    185214static int solaudio_init_out (HWVoiceOut *hw, audsettings_t *as)
    186215{
    187     solaudioVoiceOut *sol = (solaudioVoiceOut *) hw;
    188     audio_info_t audioInfo;
    189     audsettings_t obt_as;
    190     int fd = -1;
    191     int ctl_fd = -1;
    192 
    193     AUDIO_INITINFO(&audioInfo);
    194     audioInfo.play.sample_rate = as->freq;
    195     audioInfo.play.channels = as->nchannels;
    196     audioInfo.play.precision = aud_to_solfmt(as->fmt);
    197     audioInfo.play.buffer_size = conf.buffer_size;
     216    solaudioVoiceOut *pSol = (solaudioVoiceOut *)hw;
     217    audio_info_t AudioInfo;
     218    audsettings_t ObtAudioInfo;
     219    int AudioDev = -1;
     220    int AudioCtl = -1;
     221
     222    AUDIO_INITINFO(&AudioInfo);
     223    AudioInfo.play.sample_rate = as->freq;
     224    AudioInfo.play.channels = as->nchannels;
     225    AudioInfo.play.precision = aud_to_solfmt(as->fmt);
     226    AudioInfo.play.buffer_size = conf.cbBuffer;
    198227    if (as->fmt == AUD_FMT_U8)
    199         audioInfo.play.encoding = AUDIO_ENCODING_LINEAR8;
     228        AudioInfo.play.encoding = AUDIO_ENCODING_LINEAR8;
    200229    else
    201         audioInfo.play.encoding = AUDIO_ENCODING_LINEAR;
    202 
    203     if (solaudio_open(0, &audioInfo, &fd, &ctl_fd))
     230        AudioInfo.play.encoding = AUDIO_ENCODING_LINEAR;
     231
     232    if (solaudio_open(0, &AudioInfo, &AudioDev, &AudioCtl))
    204233    {
    205234        LogRel(("solaudio: solaudio_open failed\n"));
     
    207236    }
    208237
    209     sol->AudioDev = fd;
    210     sol->AudioCtl = ctl_fd;
    211     obt_as.freq = audioInfo.play.sample_rate;
    212     obt_as.nchannels = audioInfo.play.channels;
    213     obt_as.fmt = sol_to_audfmt(audioInfo.play.precision, audioInfo.play.encoding);
    214     obt_as.endianness = as->endianness;
    215 
    216     audio_pcm_init_info (&hw->info, &obt_as);
    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)
     238    pSol->AudioDev = AudioDev;
     239    pSol->AudioCtl = AudioCtl;
     240    ObtAudioInfo.freq = AudioInfo.play.sample_rate;
     241    ObtAudioInfo.nchannels = AudioInfo.play.channels;
     242    ObtAudioInfo.fmt = sol_to_audfmt(AudioInfo.play.precision, AudioInfo.play.encoding);
     243    ObtAudioInfo.endianness = as->endianness;
     244
     245    audio_pcm_init_info(&hw->info, &ObtAudioInfo);
     246    pSol->cBuffersPlayed = AudioInfo.play.eof;
     247
     248    hw->samples = AudioInfo.play.buffer_size >> hw->info.shift;
     249    pSol->pPCMBuf = RTMemAllocZ(AudioInfo.play.buffer_size);
     250    if (!pSol->pPCMBuf)
    222251    {
    223252        LogRel(("solaudio: failed to alloc %d %d bytes to pPCMBuf\n", hw->samples << hw->info.shift, hw->samples));
    224253        return -1;
    225254    }
    226     LogFlow(("solaudio: hw->samples=%d play.buffer_size=%d\n", hw->samples, audioInfo.play.buffer_size));
     255    LogFlow(("solaudio: hw->samples=%d play.buffer_size=%d\n", hw->samples, AudioInfo.play.buffer_size));
    227256    return 0;
    228257}
    229258
    230259
    231 static void solaudio_stop (solaudioVoiceOut *solvw)
     260static void solaudio_stop (solaudioVoiceOut *sol)
    232261{
    233262    LogFlow(("solaudio: stop\n"));
    234     if (solvw->AudioDev < 0 || solvw->AudioCtl < 0)
     263    if (sol->AudioDev < 0 || sol->AudioCtl < 0)
    235264    {
    236265        Log(("solaudio: invalid file descriptors\n"));
     
    238267    }
    239268
    240     if (ioctl(solvw->AudioCtl, I_SETSIG, 0) < 0)
     269    if (ioctl(sol->AudioCtl, I_SETSIG, 0) < 0)
    241270    {
    242271        LogRel(("solaudio: failed to stop signalling\n"));
     
    244273    }
    245274
    246     if (ioctl(solvw->AudioDev, I_FLUSH, FLUSHW) < 0)
     275    if (ioctl(sol->AudioDev, I_FLUSH, FLUSHW) < 0)
    247276    {
    248277        Log(("solaudio: failed to drop unplayed buffers\n"));
     
    250279    }
    251280
    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;
     281    close(sol->AudioDev);
     282    sol->AudioDev = -1;
     283    close(sol->AudioCtl);
     284    sol->AudioCtl = -1;
     285    sol->cBuffersPlayed = 0;
     286    if (sol->pPCMBuf)
     287    {
     288        RTMemFree(sol->pPCMBuf);
     289        sol->pPCMBuf = NULL;
    261290    }
    262291}
     
    271300
    272301
    273 static int solaudio_availbuf (solaudioVoiceOut *solvw)
    274 {
    275     audio_info_t audioInfo;
    276     int buffers = 0;
    277 
    278     AUDIO_INITINFO(&audioInfo);
    279     if (ioctl(solvw->AudioDev, AUDIO_GETINFO, &audioInfo) < 0)
     302static int solaudio_availbuf (solaudioVoiceOut *sol)
     303{
     304    audio_info_t AudioInfo;
     305    int cbBuffer = 0;
     306
     307    AUDIO_INITINFO(&AudioInfo);
     308    if (ioctl(sol->AudioDev, AUDIO_GETINFO, &AudioInfo) < 0)
    280309    {
    281310        Log(("solaudio: AUDIO_GETINFO ioctl failed\n"));
     
    283312    }
    284313
    285     buffers = audioInfo.play.buffer_size * (2 + audioInfo.play.eof - solvw->cBuffersPlayed);
    286 
    287     LogFlow(("avail: eof=%d samples=%d bufsize=%d bufplayed=%d avail=%d\n", audioInfo.play.eof, audioInfo.play.samples,
    288         audioInfo.play.buffer_size, solvw->cBuffersPlayed, buffers));
    289     return buffers;
    290 }
    291 
     314    cbBuffer = AudioInfo.play.buffer_size * (2 + AudioInfo.play.eof - sol->cBuffersPlayed);
     315
     316    LogFlow(("avail: eof=%d samples=%d bufsize=%d bufplayed=%d avail=%d\n", AudioInfo.play.eof, AudioInfo.play.samples,
     317        AudioInfo.play.buffer_size, sol->cBuffersPlayed, cbBuffer));
     318    return cbBuffer;
     319}
     320
     321#if 0
    292322static void solaudio_yield (solaudioVoiceOut *pSol)
    293323{
    294324    audio_info_t AudioInfo;
    295325    timespec_t WaitTimeSpec;
    296     if (ioctl (pSol->AudioDev, AUDIO_GETINFO, &AudioInfo) < 0)
     326    if (ioctl(pSol->AudioDev, AUDIO_GETINFO, &AudioInfo) < 0)
    297327        return;
    298328
    299329    WaitTimeSpec.tv_sec = 0;
    300     WaitTimeSpec.tv_nsec = 10000000;
     330    WaitTimeSpec.tv_nsec = 1000000;
    301331
    302332    while (AudioInfo.play.eof < pSol->cBuffersPlayed - 2)
     
    307337    }
    308338}
    309 
     339#endif
    310340
    311341static int solaudio_run_out (HWVoiceOut *hw)
     
    317347    st_sample_t *psSrc;
    318348
    319     csLive = audio_pcm_hw_get_live_out (hw);
     349    csLive = audio_pcm_hw_get_live_out(hw);
    320350    if (!csLive)
    321351        return 0;
    322352
    323     for (;;)
    324     {
    325         cbAvail = solaudio_availbuf (pSol);
    326         if (cbAvail > 0)
    327             break;
    328         solaudio_yield(pSol);
    329     }
     353    cbAvail = solaudio_availbuf(pSol);
     354    if (cbAvail <= 0)
     355        return 0;
    330356
    331357    csAvail   = cbAvail >> hw->info.shift; /* bytes => samples */
    332     csDecr    = audio_MIN (csLive, csAvail);
     358    csDecr    = audio_MIN(csLive, csAvail);
    333359    csSamples = csDecr;
    334360
     
    336362    {
    337363        /* split request at the end of our samples buffer */
    338         csToWrite = audio_MIN (csSamples, hw->samples - hw->rpos);
     364        csToWrite = audio_MIN(csSamples, hw->samples - hw->rpos);
    339365        cbToWrite = csToWrite << hw->info.shift;
    340366        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);
     367        pu8Dst    = advance(pSol->pPCMBuf, hw->rpos << hw->info.shift);
     368
     369        hw->clip(pu8Dst, psSrc, csToWrite);
     370
     371        cbWritten = write(pSol->AudioDev, pu8Dst, cbToWrite);
    346372        if (cbWritten < 0)
    347373            break;
     
    359385static int solaudio_ctl_out (HWVoiceOut *hw, int cmd, ...)
    360386{
    361     solaudioVoiceOut *sol = (solaudioVoiceOut *) hw;
     387    solaudioVoiceOut *pSol = (solaudioVoiceOut *) hw;
    362388    switch (cmd)
    363389    {
     
    365391        {
    366392            /* reset the eof marker and samples markers */
    367             audio_info_t audioInfo;
    368             AUDIO_INITINFO(&audioInfo);
    369             ioctl(sol->AudioDev, AUDIO_GETINFO, &audioInfo);
    370             audioInfo.play.eof = 0;
    371             audioInfo.play.samples = 0;
    372             ioctl(sol->AudioDev, AUDIO_SETINFO, &audioInfo);
    373 
    374             sol->cBuffersPlayed = 0;
    375             audio_pcm_info_clear_buf (&hw->info, sol->pPCMBuf, hw->samples);
     393            audio_info_t AudioInfo;
     394            AUDIO_INITINFO(&AudioInfo);
     395            ioctl(pSol->AudioDev, AUDIO_GETINFO, &AudioInfo);
     396            AudioInfo.play.eof = 0;
     397            AudioInfo.play.samples = 0;
     398            ioctl(pSol->AudioDev, AUDIO_SETINFO, &AudioInfo);
     399            pSol->cBuffersPlayed = 0;
     400
     401            audio_pcm_info_clear_buf(&hw->info, pSol->pPCMBuf, hw->samples);
    376402            LogFlow(("solaudio: voice_enable\n"));
    377403            break;
     
    381407        {
    382408            LogFlow(("solaudio: voice_disable\n"));
    383             solaudio_stop(sol);
     409            solaudio_stop(pSol);
    384410            break;
    385411        }
     
    422448
    423449static struct audio_option solaudio_options[] = {
    424     {"BUFFER_SIZE", AUD_OPT_INT, &conf.buffer_size,
    425      "Size of the buffer in frames", NULL, 0},
    426     {"BUFFER_COUNT", AUD_OPT_INT, &conf.nbuffers,
    427      "Number of buffers", NULL, 0},
     450    {"BUFFER_SIZE", AUD_OPT_INT, &conf.cbBuffer,
     451     "Size of the buffer in bytes", NULL, 0},
    428452    {NULL, 0, NULL, NULL, NULL, 0}
    429453};
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