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

📄 sound.cpp

📁 A*算法 A*算法 A*算法 A*算法A*算法A*算法
💻 CPP
📖 第 1 页 / 共 2 页
字号:
}
#endif

bool wxSoundSyncOnlyAdaptor::Play(wxSoundData *data, unsigned flags,
                                  volatile wxSoundPlaybackStatus *status)
{
    Stop();
    if (flags & wxSOUND_ASYNC)
    {
#if wxUSE_THREADS
        m_mutexRightToPlay.Lock();
        m_status.m_playing = true;
        m_status.m_stopRequested = false;
        data->IncRef();
        wxThread *th = new wxSoundAsyncPlaybackThread(this, data, flags);
        th->Create();
        th->Run();
        wxLogTrace(_T("sound"), _T("launched async playback thread"));
        return true;
#else
        wxLogError(_("Unable to play sound asynchronously."));
        return false;
#endif
    }
    else
    {
#if wxUSE_THREADS
        m_mutexRightToPlay.Lock();
#endif
        bool rv = m_backend->Play(data, flags, status);
#if wxUSE_THREADS
        m_mutexRightToPlay.Unlock();
#endif
        return rv;
    }
}

void wxSoundSyncOnlyAdaptor::Stop()
{
    wxLogTrace(_T("sound"), _T("asking audio to stop"));

#if wxUSE_THREADS
    // tell the player thread (if running) to stop playback ASAP:
    m_status.m_stopRequested = true;

    // acquire the mutex to be sure no sound is being played, then
    // release it because we don't need it for anything (the effect of this
    // is that calling thread will wait until playback thread reacts to
    // our request to interrupt playback):
    m_mutexRightToPlay.Lock();
    m_mutexRightToPlay.Unlock();
    wxLogTrace(_T("sound"), _T("audio was stopped"));
#endif
}

bool wxSoundSyncOnlyAdaptor::IsPlaying() const
{
#if wxUSE_THREADS
    return m_status.m_playing;
#else
    return false;
#endif
}


// ----------------------------------------------------------------------------
// wxSound
// ----------------------------------------------------------------------------

wxSoundBackend *wxSound::ms_backend = NULL;

// FIXME - temporary, until we have plugins architecture
#if wxUSE_LIBSDL
    #if wxUSE_PLUGINS
        wxDynamicLibrary *wxSound::ms_backendSDL = NULL;
    #else
        extern "C" wxSoundBackend *wxCreateSoundBackendSDL();
    #endif
#endif

wxSound::wxSound() : m_data(NULL)
{
}

wxSound::wxSound(const wxString& sFileName, bool isResource) : m_data(NULL)
{
    Create(sFileName, isResource);
}

wxSound::wxSound(int size, const wxByte* data) : m_data(NULL)
{
    Create(size, data);
}

wxSound::~wxSound()
{
    Free();
}

bool wxSound::Create(const wxString& fileName, bool isResource)
{
    wxASSERT_MSG( !isResource,
             _T("Loading sound from resources is only supported on Windows") );

    Free();

    wxFile fileWave;
    if (!fileWave.Open(fileName, wxFile::read))
    {
        return false;
    }

    wxFileOffset lenOrig = fileWave.Length();
    if ( lenOrig == wxInvalidOffset )
        return false;

    size_t len = wx_truncate_cast(size_t, lenOrig);
    wxUint8 *data = new wxUint8[len];
    if ( fileWave.Read(data, len) != lenOrig )
    {
        delete [] data;
        wxLogError(_("Couldn't load sound data from '%s'."), fileName.c_str());
        return false;
    }

    if (!LoadWAV(data, len, false))
    {
        delete [] data;
        wxLogError(_("Sound file '%s' is in unsupported format."),
                   fileName.c_str());
        return false;
    }

    return true;
}

bool wxSound::Create(int size, const wxByte* data)
{
    wxASSERT( data != NULL );

    Free();
    if (!LoadWAV(data, size, true))
    {
        wxLogError(_("Sound data are in unsupported format."));
        return false;
    }
    return true;
}

/*static*/ void wxSound::EnsureBackend()
{
    if (!ms_backend)
    {
        // FIXME -- make this fully dynamic when plugins architecture is in
        // place
#if wxUSE_LIBSDL
        //if (!ms_backend)
        {
#if !wxUSE_PLUGINS
            ms_backend = wxCreateSoundBackendSDL();
#else
            wxString dllname;
            dllname.Printf(_T("%s/%s"),
                wxDynamicLibrary::GetPluginsDirectory().c_str(),
                wxDynamicLibrary::CanonicalizePluginName(
                    _T("sound_sdl"), wxDL_PLUGIN_BASE).c_str());
            wxLogTrace(_T("sound"),
                       _T("trying to load SDL plugin from '%s'..."),
                       dllname.c_str());
            wxLogNull null;
            ms_backendSDL = new wxDynamicLibrary(dllname, wxDL_NOW);
            if (!ms_backendSDL->IsLoaded())
            {
                wxDELETE(ms_backendSDL);
            }
            else
            {
                typedef wxSoundBackend *(*wxCreateSoundBackend_t)();
                wxDYNLIB_FUNCTION(wxCreateSoundBackend_t,
                                  wxCreateSoundBackendSDL, *ms_backendSDL);
                if (pfnwxCreateSoundBackendSDL)
                {
                    ms_backend = (*pfnwxCreateSoundBackendSDL)();
                }
            }
#endif
            if (ms_backend && !ms_backend->IsAvailable())
            {
                wxDELETE(ms_backend);
            }
        }
#endif

#ifdef HAVE_SYS_SOUNDCARD_H
        if (!ms_backend)
        {
            ms_backend = new wxSoundBackendOSS();
            if (!ms_backend->IsAvailable())
            {
                wxDELETE(ms_backend);
            }
        }
#endif

        if (!ms_backend)
            ms_backend = new wxSoundBackendNull();

        if (!ms_backend->HasNativeAsyncPlayback())
            ms_backend = new wxSoundSyncOnlyAdaptor(ms_backend);

        wxLogTrace(_T("sound"),
                   _T("using backend '%s'"), ms_backend->GetName().c_str());
    }
}

/*static*/ void wxSound::UnloadBackend()
{
    if (ms_backend)
    {
        wxLogTrace(_T("sound"), _T("unloading backend"));

        Stop();

        delete ms_backend;
        ms_backend = NULL;
#if wxUSE_LIBSDL && wxUSE_PLUGINS
        delete ms_backendSDL;
#endif
    }
}

bool wxSound::DoPlay(unsigned flags) const
{
    wxCHECK_MSG( IsOk(), false, _T("Attempt to play invalid wave data") );

    EnsureBackend();
    wxSoundPlaybackStatus status;
    status.m_playing = true;
    status.m_stopRequested = false;
    return ms_backend->Play(m_data, flags, &status);
}

/*static*/ void wxSound::Stop()
{
    if (ms_backend)
        ms_backend->Stop();
}

/*static*/ bool wxSound::IsPlaying()
{
    if (ms_backend)
        return ms_backend->IsPlaying();
    else
        return false;
}

void wxSound::Free()
{
    if (m_data)
        m_data->DecRef();
}

typedef struct
{
    wxUint32      uiSize;
    wxUint16      uiFormatTag;
    wxUint16      uiChannels;
    wxUint32      ulSamplesPerSec;
    wxUint32      ulAvgBytesPerSec;
    wxUint16      uiBlockAlign;
    wxUint16      uiBitsPerSample;
} WAVEFORMAT;

#define WAVE_FORMAT_PCM  1
#define WAVE_INDEX       8
#define FMT_INDEX       12

bool wxSound::LoadWAV(const wxUint8 *data, size_t length, bool copyData)
{
    WAVEFORMAT waveformat;
    wxUint32 ul;

    if (length < 32 + sizeof(WAVEFORMAT))
        return false;

    memcpy(&waveformat, &data[FMT_INDEX + 4], sizeof(WAVEFORMAT));
    waveformat.uiSize = wxUINT32_SWAP_ON_BE(waveformat.uiSize);
    waveformat.uiFormatTag = wxUINT16_SWAP_ON_BE(waveformat.uiFormatTag);
    waveformat.uiChannels = wxUINT16_SWAP_ON_BE(waveformat.uiChannels);
    waveformat.ulSamplesPerSec = wxUINT32_SWAP_ON_BE(waveformat.ulSamplesPerSec);
    waveformat.ulAvgBytesPerSec = wxUINT32_SWAP_ON_BE(waveformat.ulAvgBytesPerSec);
    waveformat.uiBlockAlign = wxUINT16_SWAP_ON_BE(waveformat.uiBlockAlign);
    waveformat.uiBitsPerSample = wxUINT16_SWAP_ON_BE(waveformat.uiBitsPerSample);

    if (memcmp(data, "RIFF", 4) != 0)
        return false;
    if (memcmp(&data[WAVE_INDEX], "WAVE", 4) != 0)
        return false;
    if (memcmp(&data[FMT_INDEX], "fmt ", 4) != 0)
        return false;
    if (memcmp(&data[FMT_INDEX + waveformat.uiSize + 8], "data", 4) != 0)
        return false;
    memcpy(&ul,&data[FMT_INDEX + waveformat.uiSize + 12], 4);
    ul = wxUINT32_SWAP_ON_BE(ul);

    //WAS: if (ul + FMT_INDEX + waveformat.uiSize + 16 != length)
    if (ul + FMT_INDEX + waveformat.uiSize + 16 > length)
        return false;

    if (waveformat.uiFormatTag != WAVE_FORMAT_PCM)
        return false;

    if (waveformat.ulSamplesPerSec !=
        waveformat.ulAvgBytesPerSec / waveformat.uiBlockAlign)
        return false;

    m_data = new wxSoundData;
    m_data->m_channels = waveformat.uiChannels;
    m_data->m_samplingRate = waveformat.ulSamplesPerSec;
    m_data->m_bitsPerSample = waveformat.uiBitsPerSample;
    m_data->m_samples = ul / (m_data->m_channels * m_data->m_bitsPerSample / 8);
    m_data->m_dataBytes = ul;

    if (copyData)
    {
        m_data->m_dataWithHeader = new wxUint8[length];
        memcpy(m_data->m_dataWithHeader, data, length);
    }
    else
        m_data->m_dataWithHeader = (wxUint8*)data;

    m_data->m_data =
        (&m_data->m_dataWithHeader[FMT_INDEX + waveformat.uiSize + 8]);

    return true;
}


// ----------------------------------------------------------------------------
// wxSoundCleanupModule
// ----------------------------------------------------------------------------

class wxSoundCleanupModule: public wxModule
{
public:
    bool OnInit() { return true; }
    void OnExit() { wxSound::UnloadBackend(); }
    DECLARE_DYNAMIC_CLASS(wxSoundCleanupModule)
};

IMPLEMENT_DYNAMIC_CLASS(wxSoundCleanupModule, wxModule)

#endif

⌨️ 快捷键说明

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