diff --git a/core/audio_player_portaudio.cpp b/core/audio_player_portaudio.cpp index deeef2c39..2ae167822 100644 --- a/core/audio_player_portaudio.cpp +++ b/core/audio_player_portaudio.cpp @@ -171,8 +171,9 @@ void PortAudioPlayer::Stop(bool timerToo) { void PortAudioPlayer::OpenStream() { // Open stream PaError err = Pa_OpenDefaultStream(&stream,0,provider->GetChannels(),paInt16,provider->GetSampleRate(),256,16,paCallback,this); - if (err != paNoError) + if (err != paNoError) { throw wxString(_T("Failed initializing PortAudio stream with error: ") + wxString(Pa_GetErrorText(err),wxConvLocal)); + } } diff --git a/core/audio_provider.cpp b/core/audio_provider.cpp index c1e53377f..2d63a43d8 100644 --- a/core/audio_provider.cpp +++ b/core/audio_provider.cpp @@ -38,6 +38,8 @@ // Headers #include #include "audio_provider_avs.h" +#include "audio_provider_ram.h" +#include "audio_provider_hd.h" #include "options.h" #include "audio_display.h" @@ -178,11 +180,15 @@ AudioProvider *AudioProvider::GetAudioProvider(wxString filename, AudioDisplay * } // Change provider to RAM/HD cache if needed - if (false) { + int cacheMode = Options.AsInt(_T("Audio Cache")); + if (cacheMode) { AudioProvider *final = NULL; - //final = new RAMAudioProvider(provider); - //final = new HDAudioProvider(provider); + // Convert to RAM + if (cacheMode == 1) final = new RAMAudioProvider(provider); + + // Convert to HD + //if (cacheMode == 2) final = new HDAudioProvider(provider); // Reassign if (final) { diff --git a/core/audio_provider.h b/core/audio_provider.h index 64eefacda..09cc45127 100644 --- a/core/audio_provider.h +++ b/core/audio_provider.h @@ -40,10 +40,6 @@ /////////// // Headers #include -#include -#include -#include "avisynth_wrap.h" -#include "audio_player.h" ////////////// diff --git a/core/audio_provider_avs.cpp b/core/audio_provider_avs.cpp index ac6580994..fe6cd00f9 100644 --- a/core/audio_provider_avs.cpp +++ b/core/audio_provider_avs.cpp @@ -48,16 +48,11 @@ #include "main.h" #include "dialog_progress.h" -#define CacheBits ((22)) -#define CacheBlockSize ((1 << CacheBits)) ////////////// // Constructor AvisynthAudioProvider::AvisynthAudioProvider(wxString _filename) { type = AUDIO_PROVIDER_NONE; - blockcache = NULL; - blockcount = 0; - blockcount = 0; filename = _filename; @@ -89,14 +84,6 @@ void AvisynthAudioProvider::Unload() { file_cache.close(); wxRemoveFile(DiskCacheName()); } - - // Free ram cache - if (blockcache) { - for (int i = 0; i < blockcount; i++) - if (blockcache[i]) - delete blockcache[i]; - delete blockcache; - } } @@ -158,76 +145,8 @@ void AvisynthAudioProvider::LoadFromClip(AVSValue _clip) { sample_rate = vi.SamplesPerSecond(); bytes_per_sample = vi.BytesPerAudioSample(); - // Read whole thing into ram cache - if (Options.AsInt(_T("Audio Cache")) == 1) { - ConvertToRAMCache(tempclip); - clip = NULL; - } - - // Disk cache - else if (Options.AsInt(_T("Audio Cache")) == 2) { - ConvertToDiskCache(tempclip); - clip = NULL; - } - - // Assign to avisynth - else { - clip = tempclip; - } -} - - -///////////// -// RAM Cache -void AvisynthAudioProvider::ConvertToRAMCache(PClip &tempclip) { - - // Allocate cache - __int64 ssize = num_samples * bytes_per_sample; - blockcount = (ssize + CacheBlockSize - 1) >> CacheBits; - - blockcache = new char*[blockcount]; - for (int i = 0; i < blockcount; i++) - blockcache[i] = NULL; - - try { - for (int i = 0; i < blockcount; i++) - blockcache[i] = new char[MIN(CacheBlockSize,ssize-i*CacheBlockSize)]; - } catch (...) { - for (int i = 0; i < blockcount; i++) - delete blockcache[i]; - delete blockcache; - - blockcache = NULL; - blockcount = 0; - - if (wxMessageBox(_("Not enough ram available. Use disk cache instead?"),_("Audio Information"),wxICON_INFORMATION | wxYES_NO) == wxYES) { - ConvertToDiskCache(tempclip); - return; - } else - throw wxString(_T("Couldn't open audio, not enough ram available.")); - } - - // Start progress - volatile bool canceled = false; - DialogProgress *progress = new DialogProgress(NULL,_("Load audio"),&canceled,_("Reading into RAM"),0,num_samples); - progress->Show(); - progress->SetProgress(0,1); - - // Read cache - int readsize = CacheBlockSize / bytes_per_sample; - - for (int i=0;iGetAudio((char*)blockcache[i],i*readsize, i == blockcount-1 ? (num_samples - i*readsize) : readsize,env); - progress->SetProgress(i,blockcount-1); - } - - type = AUDIO_PROVIDER_CACHE; - - // Clean up progress - if (!canceled) - progress->Destroy(); - else - throw wxString(_T("Audio loading cancelled by user")); + // Set + clip = tempclip; } @@ -283,7 +202,6 @@ int aaa = 0; ///////////// // Get audio void AvisynthAudioProvider::GetAudio(void *buf, __int64 start, __int64 count) { - // Requested beyond the length of audio if (start+count > num_samples) { __int64 oldcount = count; @@ -306,30 +224,8 @@ void AvisynthAudioProvider::GetAudio(void *buf, __int64 start, __int64 count) { } if (count) { - char *charbuf = (char *)buf; - - // RAM Cache - if (type == AUDIO_PROVIDER_CACHE) { - int i = (start*bytes_per_sample) >> CacheBits; - int start_offset = (start*bytes_per_sample) & (CacheBlockSize-1); - - __int64 bytesremaining = count*bytes_per_sample; - - while (bytesremaining) { - int readsize=MIN(bytesremaining,CacheBlockSize); - readsize = MIN(readsize,CacheBlockSize - start_offset); - - memcpy(charbuf,(char *)(blockcache[i++]+start_offset),readsize); - - charbuf+=readsize; - - start_offset=0; - bytesremaining-=readsize; - } - } - // Disk cache - else if (type == AUDIO_PROVIDER_DISK_CACHE) { + if (type == AUDIO_PROVIDER_DISK_CACHE) { wxMutexLocker disklock(diskmutex); file_cache.seekg(start*bytes_per_sample); file_cache.read((char*)buf,count*bytes_per_sample*channels); diff --git a/core/audio_provider_avs.h b/core/audio_provider_avs.h index ebd308e15..db3bca7b7 100644 --- a/core/audio_provider_avs.h +++ b/core/audio_provider_avs.h @@ -53,7 +53,6 @@ enum AudioProviderType { AUDIO_PROVIDER_NONE, AUDIO_PROVIDER_AVS, - AUDIO_PROVIDER_CACHE, AUDIO_PROVIDER_DISK_CACHE }; @@ -64,19 +63,12 @@ class AvisynthAudioProvider : public AudioProvider, public AviSynthWrapper { private: wxMutex diskmutex; - AudioProviderType type; - - char** blockcache; - int blockcount; - - AudioDisplay *display; - std::ifstream file_cache; + AudioProviderType type; wxString filename; PClip clip; - void ConvertToRAMCache(PClip &tempclip); void ConvertToDiskCache(PClip &tempclip); void LoadFromClip(AVSValue clip); void OpenAVSAudio(); diff --git a/core/audio_provider_hd.cpp b/core/audio_provider_hd.cpp new file mode 100644 index 000000000..d4dea8cb0 --- /dev/null +++ b/core/audio_provider_hd.cpp @@ -0,0 +1,38 @@ +// Copyright (c) 2005-2006, Rodrigo Braz Monteiro +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of the Aegisub Group nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// ----------------------------------------------------------------------------- +// +// AEGISUB +// +// Website: http://aegisub.cellosoft.com +// Contact: mailto:zeratul@cellosoft.com +// + + +/////////// +// Headers \ No newline at end of file diff --git a/core/audio_provider_hd.h b/core/audio_provider_hd.h new file mode 100644 index 000000000..e69de29bb diff --git a/core/audio_provider_ram.cpp b/core/audio_provider_ram.cpp new file mode 100644 index 000000000..df9e90e73 --- /dev/null +++ b/core/audio_provider_ram.cpp @@ -0,0 +1,169 @@ +// Copyright (c) 2005-2006, Rodrigo Braz Monteiro, Fredrik Mellbin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of the Aegisub Group nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// ----------------------------------------------------------------------------- +// +// AEGISUB +// +// Website: http://aegisub.cellosoft.com +// Contact: mailto:zeratul@cellosoft.com +// + + +/////////// +// Headers +#include "dialog_progress.h" +#include "audio_provider_ram.h" +#include "utils.h" + + +/////////// +// Defines +#define CacheBits ((22)) +#define CacheBlockSize ((1 << CacheBits)) + + +/////////////// +// Constructor +RAMAudioProvider::RAMAudioProvider(AudioProvider *source) { + // Init + blockcache = NULL; + blockcount = 0; + + // Allocate cache + __int64 ssize = source->GetNumSamples() * source->GetBytesPerSample(); + blockcount = (ssize + CacheBlockSize - 1) >> CacheBits; + blockcache = new char*[blockcount]; + for (int i = 0; i < blockcount; i++) { + blockcache[i] = NULL; + } + + // Allocate cache blocks + try { + for (int i = 0; i < blockcount; i++) { + blockcache[i] = new char[MIN(CacheBlockSize,ssize-i*CacheBlockSize)]; + } + } + catch (...) { + Clear(); + throw wxString(_T("Couldn't open audio, not enough ram available.")); + } + + // Copy data + bytes_per_sample = source->GetBytesPerSample(); + num_samples = source->GetNumSamples(); + channels = source->GetChannels(); + sample_rate = source->GetSampleRate(); + filename = source->GetFilename(); + + // Start progress + volatile bool canceled = false; + DialogProgress *progress = new DialogProgress(NULL,_("Load audio"),&canceled,_("Reading into RAM"),0,source->GetNumSamples()); + progress->Show(); + progress->SetProgress(0,1); + + // Read cache + int readsize = CacheBlockSize / source->GetBytesPerSample(); + for (int i=0;iGetAudio((char*)blockcache[i],i*readsize, i == blockcount-1 ? (num_samples - i*readsize) : readsize,env); + source->GetAudio((char*)blockcache[i],i*readsize, i == blockcount-1 ? (source->GetNumSamples() - i*readsize) : readsize); + progress->SetProgress(i,blockcount-1); + } + + // Clean up progress + if (!canceled) progress->Destroy(); + else throw wxString(_T("Audio loading cancelled by user")); +} + + +////////////// +// Destructor +RAMAudioProvider::~RAMAudioProvider() { + Clear(); +} + + +///////// +// Clear +void RAMAudioProvider::Clear() { + // Free ram cache + if (blockcache) { + for (int i = 0; i < blockcount; i++) { + delete [] blockcache[i]; + } + delete [] blockcache; + } + blockcache = NULL; + blockcount = 0; +} + + +///////////// +// Get audio +void RAMAudioProvider::GetAudio(void *buf, __int64 start, __int64 count) { + // Requested beyond the length of audio + if (start+count > num_samples) { + __int64 oldcount = count; + count = num_samples-start; + if (count < 0) count = 0; + + // Fill beyond with zero + if (bytes_per_sample == 1) { + char *temp = (char *) buf; + for (int i=count;i> CacheBits; + int start_offset = (start*bytes_per_sample) & (CacheBlockSize-1); + __int64 bytesremaining = count*bytes_per_sample; + + // Copy + while (bytesremaining) { + int readsize=MIN(bytesremaining,CacheBlockSize); + readsize = MIN(readsize,CacheBlockSize - start_offset); + + memcpy(charbuf,(char *)(blockcache[i++]+start_offset),readsize); + + charbuf+=readsize; + + start_offset=0; + bytesremaining-=readsize; + } + } +} diff --git a/core/audio_provider_ram.h b/core/audio_provider_ram.h new file mode 100644 index 000000000..fe3feaba6 --- /dev/null +++ b/core/audio_provider_ram.h @@ -0,0 +1,59 @@ +// Copyright (c) 2006, Rodrigo Braz Monteiro +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of the Aegisub Group nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// ----------------------------------------------------------------------------- +// +// AEGISUB +// +// Website: http://aegisub.cellosoft.com +// Contact: mailto:zeratul@cellosoft.com +// + + +#pragma once + + +/////////// +// Headers +#include "audio_provider.h" + + +//////////////////////// +// Audio provider class +class RAMAudioProvider : public AudioProvider { +private: + char** blockcache; + int blockcount; + + void Clear(); + +public: + RAMAudioProvider(AudioProvider *source); + ~RAMAudioProvider(); + + void GetAudio(void *buf, __int64 start, __int64 count); +};