You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
177 lines
6.0 KiB
177 lines
6.0 KiB
/*==LICENSE==* |
|
|
|
CyanWorlds.com Engine - MMOG client, server and tools |
|
Copyright (C) 2011 Cyan Worlds, Inc. |
|
|
|
This program is free software: you can redistribute it and/or modify |
|
it under the terms of the GNU General Public License as published by |
|
the Free Software Foundation, either version 3 of the License, or |
|
(at your option) any later version. |
|
|
|
This program is distributed in the hope that it will be useful, |
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
GNU General Public License for more details. |
|
|
|
You should have received a copy of the GNU General Public License |
|
along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
|
|
You can contact Cyan Worlds, Inc. by email legal@cyan.com |
|
or by snail mail at: |
|
Cyan Worlds, Inc. |
|
14617 N Newport Hwy |
|
Mead, WA 99021 |
|
|
|
*==LICENSE==*/ |
|
////////////////////////////////////////////////////////////////////////////// |
|
// // |
|
// plAudioFileReader // |
|
// // |
|
//// Notes /////////////////////////////////////////////////////////////////// |
|
// // |
|
// 3.5.2001 - Created by mcn. // |
|
// // |
|
////////////////////////////////////////////////////////////////////////////// |
|
#include <string.h> |
|
|
|
#include "hsTypes.h" |
|
#include "plAudioFileReader.h" |
|
#include "plAudioCore.h" |
|
//#include "hsTimer.h" |
|
#include "hsUtils.h" |
|
#include "plFile/hsFiles.h" |
|
#include "plFile/plFileUtils.h" |
|
#include "plUnifiedTime/plUnifiedTime.h" |
|
#include "plBufferedFileReader.h" |
|
#include "plCachedFileReader.h" |
|
#include "plFastWavReader.h" |
|
#include "plOGGCodec.h" |
|
#include "plWavFile.h" |
|
|
|
#define kCacheDirName "temp" |
|
|
|
static void hsStrUpper(char *s) |
|
{ |
|
if (s) |
|
{ |
|
int len = hsStrlen(s); |
|
for (int i = 0; i < len; i++) |
|
s[i] = toupper(s[i]); |
|
} |
|
} |
|
|
|
plAudioFileReader* plAudioFileReader::CreateReader(const char* path, plAudioCore::ChannelSelect whichChan, StreamType type) |
|
{ |
|
const char* ext = plFileUtils::GetFileExt(path); |
|
|
|
if (type == kStreamWAV) |
|
{ |
|
bool isWav = (stricmp(ext, "wav") == 0); |
|
// We want to stream a wav off disk, but this is a compressed file. |
|
// Get the uncompressed path. Ignore the requested channel, since it |
|
// will have already been split into two files if that is necessary. |
|
if (!isWav) |
|
{ |
|
char cachedPath[256]; |
|
IGetCachedPath(path, cachedPath, whichChan); |
|
plAudioFileReader *r = TRACKED_NEW plCachedFileReader(cachedPath, plAudioCore::kAll); |
|
if (!r->IsValid()) { |
|
// So we tried to play a cached file and it didn't exist |
|
// Oops... we should cache it now |
|
delete r; |
|
ICacheFile(path, true, whichChan); |
|
r = TRACKED_NEW plCachedFileReader(cachedPath, plAudioCore::kAll); |
|
} |
|
return r; |
|
} |
|
|
|
plAudioFileReader *r = TRACKED_NEW plFastWAV(path, whichChan); |
|
return r; |
|
} |
|
else if (type == kStreamRAM) |
|
return TRACKED_NEW plBufferedFileReader(path, whichChan); |
|
else if (type == kStreamNative) |
|
return TRACKED_NEW plOGGCodec(path, whichChan); |
|
|
|
return nil; |
|
} |
|
|
|
plAudioFileReader* plAudioFileReader::CreateWriter(const char* path, plWAVHeader& header) |
|
{ |
|
const char* ext = plFileUtils::GetFileExt(path); |
|
|
|
plAudioFileReader* writer = TRACKED_NEW plCachedFileReader(path, plAudioCore::kAll); |
|
writer->OpenForWriting(path, header); |
|
return writer; |
|
} |
|
|
|
void plAudioFileReader::IGetCachedPath(const char* path, char* cachedPath, plAudioCore::ChannelSelect whichChan) |
|
{ |
|
// Get the file's path and add our streaming cache folder to it |
|
strcpy(cachedPath, path); |
|
plFileUtils::StripFile(cachedPath); |
|
strcat(cachedPath, kCacheDirName"\\"); |
|
|
|
// Create the directory first |
|
plFileUtils::CreateDir(cachedPath); |
|
|
|
// Get the path to the cached version of the file, without the extension |
|
const char* fileName = plFileUtils::GetFileName(path); |
|
const char* fileExt = plFileUtils::GetFileExt(fileName); |
|
strncat(cachedPath, fileName, fileExt-fileName-1); |
|
|
|
if (whichChan == plAudioCore::kLeft) |
|
strcat(cachedPath, "-Left.tmp"); |
|
else if (whichChan == plAudioCore::kRight) |
|
strcat(cachedPath, "-Right.tmp"); |
|
else if (whichChan == plAudioCore::kAll) |
|
strcat(cachedPath, ".tmp"); |
|
} |
|
|
|
void plAudioFileReader::ICacheFile(const char* path, bool noOverwrite, plAudioCore::ChannelSelect whichChan) |
|
{ |
|
char cachedPath[256]; |
|
IGetCachedPath(path, cachedPath, whichChan); |
|
if (!noOverwrite || !plFileUtils::FileExists(cachedPath)) |
|
{ |
|
plAudioFileReader* reader = plAudioFileReader::CreateReader(path, whichChan, kStreamNative); |
|
if (!reader || !reader->IsValid()) |
|
{ |
|
delete reader; |
|
return; |
|
} |
|
plAudioFileReader* writer = CreateWriter(cachedPath, reader->GetHeader()); |
|
if (!writer || !writer->IsValid()) |
|
{ |
|
delete reader; |
|
delete writer; |
|
return; |
|
} |
|
|
|
UInt8 buffer[4096]; |
|
UInt32 numLeft; |
|
while ((numLeft = reader->NumBytesLeft()) > 0) |
|
{ |
|
UInt32 toRead = (numLeft < sizeof(buffer)) ? numLeft : sizeof(buffer); |
|
reader->Read(toRead, buffer); |
|
writer->Write(toRead, buffer); |
|
} |
|
writer->Close(); |
|
|
|
delete writer; |
|
delete reader; |
|
} |
|
} |
|
|
|
void plAudioFileReader::CacheFile(const char* path, bool splitChannels, bool noOverwrite) |
|
{ |
|
if (splitChannels) |
|
{ |
|
ICacheFile(path, noOverwrite, plAudioCore::kLeft); |
|
ICacheFile(path, noOverwrite, plAudioCore::kRight); |
|
} |
|
else |
|
{ |
|
ICacheFile(path, noOverwrite, plAudioCore::kAll); |
|
} |
|
}
|
|
|