⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sdlaudio_drv.c

📁 audio-video-codecs.rar语音编解码器
💻 C
字号:
/*
//
//                  INTEL CORPORATION PROPRIETARY INFORMATION
//     This software is supplied under the terms of a license agreement or
//     nondisclosure agreement with Intel Corporation and may not be copied
//     or disclosed except in accordance with the terms of that agreement.
//       Copyright(c) 2003-2006 Intel Corporation. All Rights Reserved.
//
*/

#include "umc_defs.h"

#ifdef UMC_ENABLE_SDL_AUDIO_RENDER

#include "sdlaudio_drv.h"
#include "vm_time.h"

#define SDLAUDIO_OK   0
#define SDLAUDIO_ERR -1

#define SDLAUDIO_OFF  0
#define SDLAUDIO_ON   1

#define SDLAUDIO_DELAY 10

void sdlaudioCallback(void *driver, Uint8 *stream, Ipp32s len);
static Ipp32s audio_data_remove(SDLAudioDrv *drv,
                                Ipp8u *data,
                                Ipp32s size);
static Ipp32s audio_data_add(SDLAudioDrv *drv,
                             Ipp8u *data,
                             Ipp32s size);

void *sdlaudioInit(const Ipp32u freq,
                   const Ipp32u channels,
                   const Ipp32u bps)
{
    SDL_AudioSpec wanted_spec, spec;
    Uint32 subsystems_init;

    Ipp32u sSize = 0;
    Ipp32s result = SDLAUDIO_OK;
    SDLAudioDrv *drv =(SDLAudioDrv *)ippsMalloc_8u(sizeof(SDLAudioDrv));

    /* Loading audio stream parameters to the drv structure. */
    drv->mFrequency = freq;
    drv->mChannels = channels;
    drv->mBitPerSample = bps;

    /* SDL audio subsystem initialization. */
    subsystems_init = SDL_WasInit(SDL_INIT_EVERYTHING);
    if (!subsystems_init)
        result = SDL_Init(SDL_INIT_AUDIO);
    else if (!(SDL_INIT_AUDIO & subsystems_init))
        result = SDL_InitSubSystem(SDL_INIT_AUDIO);

    if (SDLAUDIO_ERR == result)
    {
        vm_debug_trace(VM_DEBUG_NONE, VM_STRING("SDLAudio:" "Init:SDL_Init(SubSystem)" " FAILED"));
        return NULL;
    }

    /* Some drv initialization. */
    vm_mutex_set_invalid(&(drv->mLockSender));
    result = vm_mutex_init(&(drv->mLockSender));
    CHECK_RESULT(VM_OK, "Init:MutexInit", NULL)

    vm_mutex_set_invalid(&(drv->mLockBuffer));
    result = vm_mutex_init(&(drv->mLockBuffer));
    CHECK_RESULT(VM_OK, "Init:MutexInit", NULL)

    /* Setting SDL specification an opening audio device. */
    wanted_spec.channels    = (Uint8)drv->mChannels;
    wanted_spec.freq        = drv->mFrequency;
    wanted_spec.format      = SDLAUDIO_FORMAT;
    wanted_spec.samples     = SDLAUDIO_SAMPLES;
    wanted_spec.userdata    = drv;
    wanted_spec.callback    = sdlaudioCallback;

    result = SDL_OpenAudio(&wanted_spec, &spec);
    CHECK_RESULT(SDLAUDIO_OK, "Init:SDL_OpenAudio", NULL)

    /* Audio unit frames buffer size check */
    drv->mChunkSize = SDLAUDIO_BUFFERS_SIZE;

    sSize = sizeof(drv->mChunkSize);

    /* Buffers allocation and setup. */
    drv->mChunksNumber = SDLAUDIO_BUFFERS_NUM;
    drv->mBufferSize =(drv->mChunksNumber + 1) * drv->mChunkSize;
    drv->mDataBuffer =(Ipp8u *)ippsMalloc_8u(drv->mBufferSize);
    drv->mReadPosition = 0;
    drv->mWritePosition = 0;

    /* Starting audio processing */
    SDL_PauseAudio (SDLAUDIO_OFF);

    drv->mVolume = 1.0;
    drv->mRenderFlag = SDLAUDIO_RENDER_OPEN;
    return drv;
}

/**
 * Add audio data to ringbuffer
 */
static Ipp32s audio_data_add(SDLAudioDrv *drv,
                             Ipp8u* data,
                             Ipp32s size)
{
    Ipp32s offset, free;

    if (NULL == drv) return size;
    offset = drv->mBufferSize - drv->mWritePosition;
    /* Number of free bytes in the buffer */
    free = drv->mReadPosition - drv->mWritePosition - drv->mChunkSize;

    if (free < 0) free += drv->mBufferSize;

    if (size > free) size = free;
    if (offset > size) offset = size;

    /* Till end of buffer */
    //memcpy(&drv->mDataBuffer[drv->mWritePosition], data, offset);
    ippsCopy_8u(data, &drv->mDataBuffer[drv->mWritePosition], offset);

    /* We have to wrap around */
    if (size > offset)
    {
        /* remaining part from beginning of buffer */
        //memcpy(drv->mDataBuffer, &data[offset], size - offset);
        ippsCopy_8u(&data[offset], drv->mDataBuffer, size - offset);
    }

    drv->mWritePosition =(drv->mWritePosition + size) % drv->mBufferSize;
    return size;
}

/**
 * Remove data from ringbuffer
 */
static Ipp32s audio_data_remove(SDLAudioDrv *drv,
                                Ipp8u* data,
                                Ipp32s size)
{
    Ipp32s offset, buffered;

    if (NULL == drv) return size;
    offset = drv->mBufferSize - drv->mReadPosition;
    /* Number of buffered bytes */
    buffered = drv->mWritePosition - drv->mReadPosition;

    if (buffered < 0) buffered += drv->mBufferSize;

    if (size > buffered) size = buffered;
    if (offset > size) offset = size;

    /* Till end of buffer */
    //memcpy(data, &drv->mDataBuffer[drv->mReadPosition], offset);
    //ippsCopy_8u(&drv->mDataBuffer[drv->mReadPosition], data, offset);
    SDL_MixAudio(data, &drv->mDataBuffer[drv->mReadPosition], offset,
                 (Ipp32s)(drv->mVolume * SDL_MIX_MAXVOLUME));

    /* We have to wrap around */
    if (size > offset)
    {
        /* remaining part from beginning of buffer */
        //memcpy(&data[offset], drv->mDataBuffer, size - offset);
        //ippsCopy_8u(drv->mDataBuffer, &data[offset], size - offset);
        SDL_MixAudio (&data[offset], drv->mDataBuffer, size - offset,
            (Ipp32s)(drv->mVolume * SDL_MIX_MAXVOLUME));
    }
    drv->mReadPosition = (drv->mReadPosition + size) % drv->mBufferSize;
    return size;
}

Ipp32s sdlaudioPlay(void *driver,
                    Ipp8u* buf,
                    Ipp32s size)
{
    SDLAudioDrv *drv = (SDLAudioDrv *)driver;
    Ipp32s added;

    if (NULL == drv) return 0;
    /*
     * Eduard Martirosyan:
     * This is a hack. Actualy we don't need to use mLockSender and mRenderFlag.
     * But UMC run SendFrame() after Close(). Why?
     */
    vm_mutex_lock(&(drv->mLockSender));
    if (drv->mRenderFlag == SDLAUDIO_RENDER_OPEN)
    {
        while (size > 0)
        {
            vm_mutex_lock(&(drv->mLockBuffer));
            added = audio_data_add(drv, buf, size);
            vm_mutex_unlock(&(drv->mLockBuffer));
            buf += added;
            size -= added;
            /* Increasing of productivity: */
            if (size > 0) vm_time_sleep (SDLAUDIO_DELAY);
        }
    }
    vm_mutex_unlock(&(drv->mLockSender));
    return 0;
}

Ipp32s sdlaudioReset(void *driver)
{
    SDLAudioDrv *drv =(SDLAudioDrv *)driver;
    SDL_AudioSpec wanted_spec, spec;
    SDL_audiostatus stat;

    if (NULL == drv) return 0;
    /* Reseting an audio device. */
    SDL_LockAudio ();
    stat = SDL_GetAudioStatus ();
    SDL_PauseAudio (SDLAUDIO_ON);
    SDL_UnlockAudio ();
    SDL_CloseAudio ();

    wanted_spec.channels    = (Uint8)drv->mChannels;
    wanted_spec.freq        = drv->mFrequency;
    wanted_spec.format      = SDLAUDIO_FORMAT;
    wanted_spec.samples     = SDLAUDIO_SAMPLES;
    wanted_spec.userdata    = drv;
    wanted_spec.callback    = sdlaudioCallback;

    SDL_OpenAudio(&wanted_spec, &spec);

    drv->mReadPosition = 0;
    drv->mWritePosition = 0;

    if (stat == SDL_AUDIO_PLAYING) SDL_PauseAudio (SDLAUDIO_OFF);
    else SDL_PauseAudio (SDLAUDIO_ON);
    return 0;
}

Ipp32s sdlaudioPause(void *driver)
{
    SDLAudioDrv *drv = (SDLAudioDrv *)driver;

    if (NULL == drv) return 0;
    /* Stopping audio processing */
    SDL_LockAudio ();
    SDL_PauseAudio (SDLAUDIO_ON);
    SDL_UnlockAudio ();
    return 0;
}

Ipp32s sdlaudioResume(void *driver)
{
    SDLAudioDrv *drv = (SDLAudioDrv *)driver;

    if (NULL == drv) return 0;
    /* Starting audio processing */
    SDL_LockAudio ();
    SDL_PauseAudio (SDLAUDIO_OFF);
    SDL_UnlockAudio ();
    return 0;
}

Ipp32f sdlaudioSetVolume (void *driver, Ipp32f volume)
{
    SDLAudioDrv *drv = (SDLAudioDrv *)driver;

    if (NULL == drv) return 0;
    if (volume < 0)
        drv->mVolume = 0;
    else if (volume > SDL_MIX_MAXVOLUME)
        drv->mVolume = 1;
    else
        drv->mVolume = volume;
    return drv->mVolume;
}

Ipp32f sdlaudioGetVolume (void *driver)
{
    SDLAudioDrv *drv = (SDLAudioDrv *)driver;

    if (NULL == drv) return 0;
    return drv->mVolume;
}

void sdlaudioClose(void *driver)
{
    SDLAudioDrv *drv = (SDLAudioDrv *)driver;
    Uint32 subsystems_init;

    if (NULL == drv) return;
    vm_mutex_lock(&(drv->mLockSender));
    vm_mutex_lock(&(drv->mLockBuffer));
    drv->mRenderFlag = SDLAUDIO_RENDER_CLOSE;

    /* Stopping audio processing. */
    sdlaudioPause (driver);
    SDL_CloseAudio ();

    subsystems_init = SDL_WasInit(SDL_INIT_EVERYTHING);
    if (SDL_INIT_EVERYTHING & (!SDL_INIT_AUDIO) & subsystems_init)
        SDL_Quit();
    else if (SDL_INIT_AUDIO & subsystems_init)
        SDL_QuitSubSystem(SDL_INIT_AUDIO);

    vm_mutex_unlock(&(drv->mLockSender));
    vm_mutex_unlock(&(drv->mLockBuffer));

    vm_mutex_destroy(&(drv->mLockBuffer));
    vm_mutex_destroy(&(drv->mLockSender));

    ippsFree(drv->mDataBuffer);
    ippsFree(drv);
}

void sdlaudioCallback(void *driver, Uint8 *stream, Ipp32s len)
{
    SDLAudioDrv *drv = (SDLAudioDrv *)driver;
    Ipp32s buffered;

    if (NULL == drv) return;
    vm_mutex_lock(&(drv->mLockBuffer));

    /* Number of buffered bytes */
    buffered = drv->mWritePosition - drv->mReadPosition;
    if (buffered < 0) buffered += drv->mBufferSize;

    if (buffered > len) buffered = len;

    if (buffered)
    {
        audio_data_remove(drv, (Ipp8u *)stream, buffered);
    }
    vm_mutex_unlock(&(drv->mLockBuffer));
}

#endif // UMC_ENABLE_SDL_AUDIO_RENDER

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -