00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "LampBasic.h"
00026 #include "Sound/Reader/OggVorbisReader.h"
00027 #include "vorbis/vorbisfile.h"
00028
00029 namespace Lamp{
00030
00031
00032
00033
00034
00035
00036
00037 class OggVorbisReaderImpl{
00038 public:
00039
00040
00041
00042
00043 OggVorbisReaderImpl(const FilePath& filePath) : filePath_(filePath),
00044 file_(NULL), cursor_(0), pcmScale_(0),
00045 size_(0), sample_(0), channel_(0), bit_(0),
00046 oggVorbisinitialized_(false), initialized_(false){
00047 ::memset(&oggVorbis_, 0, sizeof(OggVorbis_File));
00048 }
00049
00050
00051
00052
00053 virtual ~OggVorbisReaderImpl(){
00054 int result;
00055 if(file_ != NULL){
00056 if(oggVorbisinitialized_){
00057 result = ov_clear(&oggVorbis_);
00058 Assert(result == 0);
00059 }else{
00060 result = fclose(file_);
00061 Assert(result == 0);
00062 }
00063 }
00064 }
00065
00066
00067
00068
00069
00070
00071 virtual u_int getSize() const{
00072 Assert(initialized_);
00073 return size_;
00074 }
00075
00076
00077
00078
00079
00080 virtual int getSample() const{
00081 Assert(initialized_);
00082 return sample_;
00083 }
00084
00085
00086
00087
00088
00089 virtual int getChannel() const{
00090 Assert(initialized_);
00091 return channel_;
00092 }
00093
00094
00095
00096
00097
00098 virtual int getBit() const{
00099 Assert(initialized_);
00100 return bit_;
00101 }
00102
00103
00104
00105
00106
00107 virtual const String& getComment(){
00108 Assert(initialized_);
00109 return comment_;
00110 }
00111
00112
00113
00114
00115
00116
00117 virtual void setCursor(u_int cursor){
00118 Assert((cursor % pcmScale_) == 0);
00119 if(ov_pcm_seek(&oggVorbis_, cursor / pcmScale_) != 0){
00120 ErrorOut("OggVorbisReader::setCursor() 位置の設定に失敗しました。");
00121 }
00122 cursor_ = cursor;
00123 }
00124
00125
00126
00127
00128
00129 virtual u_int getCursor(){ return cursor_; }
00130
00131
00132
00133
00134
00135
00136 virtual bool readHeader(){
00137 if(!filePath_.existFile()){ return false; }
00138 file_ = fopen(filePath_.getPath().getBytes(), "rb");
00139 if(file_ == NULL){ return false; }
00140
00141 ::memset(&oggVorbis_, 0, sizeof(OggVorbis_File));
00142 int result = ov_open(file_, &oggVorbis_, NULL, 0);
00143
00144 if(result < 0){ return false; }
00145 oggVorbisinitialized_ = true;
00146
00147 if(ov_seekable(&oggVorbis_) == 0){ return false; }
00148
00149 vorbis_info* info = ov_info(&oggVorbis_, -1);
00150 if(info == NULL){ return false; }
00151 sample_ = info->rate;
00152 Assert((sample_ >= DSBFREQUENCY_MIN) && (sample_ <= 100000));
00153 channel_ = info->channels;
00154 Assert((channel_ == 1) || (channel_ == 2));
00155
00156 bit_ = 16;
00157 Assert((bit_ == 8) || (bit_ == 16));
00158 pcmScale_ = 2 * channel_;
00159
00160 __int64 size = ov_pcm_total(&oggVorbis_, -1);
00161 if(size < 0){ return false; }
00162 size *= pcmScale_;
00163 if(size > Limit::uIntMax){ return false; }
00164 size_ = (u_int)size;
00165
00166 vorbis_comment* commnets = ov_comment(&oggVorbis_,-1);
00167 int commentCount = commnets->comments;
00168 for(int i = 0; i < commentCount; i++){
00169 String comment = commnets->user_comments[i];
00170 if(comment.startsWith("COMMENT=")){
00171 comment_ = comment.getSubstring(8);
00172 }
00173 }
00174 setCursor(0);
00175 initialized_ = true;
00176 return true;
00177 }
00178
00179
00180
00181
00182
00183
00184
00185
00186 virtual int read(void* buffer, u_int size){
00187 char* readBuffer = (char*)buffer;
00188 int readSize = 0;
00189 while(true){
00190
00191 int result = ov_read(&oggVorbis_,
00192 (readBuffer + readSize), (size - readSize), 0, 2, 1, NULL);
00193 if(result < 0){ return -1; }
00194 readSize += result;
00195 cursor_ += result;
00196 if((size == readSize) || (result == 0)){ break; }
00197 }
00198 Assert(size == readSize);
00199 return readSize;
00200 }
00201
00202 private:
00203
00204
00205 FilePath filePath_;
00206
00207 FILE* file_;
00208
00209 OggVorbis_File oggVorbis_;
00210
00211 String comment_;
00212
00213 u_int cursor_;
00214
00215 u_int pcmScale_;
00216
00217
00218 u_int size_;
00219
00220 int sample_;
00221
00222 int channel_;
00223
00224 int bit_;
00225
00226 bool oggVorbisinitialized_;
00227
00228 bool initialized_;
00229
00230 };
00231
00232
00233
00234
00235 OggVorbisReader::OggVorbisReader(const FilePath& filePath){
00236 implement_ = new OggVorbisReaderImpl(filePath);
00237 }
00238
00239
00240 OggVorbisReader::~OggVorbisReader(){
00241 SafeDelete(implement_);
00242 }
00243
00244
00245 u_int OggVorbisReader::getSize() const{ return implement_->getSize(); }
00246
00247
00248 int OggVorbisReader::getSample() const{ return implement_->getSample(); }
00249
00250
00251 int OggVorbisReader::getChannel() const{ return implement_->getChannel(); }
00252
00253
00254 int OggVorbisReader::getBit() const{ return implement_->getBit(); }
00255
00256
00257 const String& OggVorbisReader::getComment(){ return implement_->getComment(); }
00258
00259
00260 void OggVorbisReader::setCursor(u_int cursor){
00261 implement_->setCursor(cursor);
00262 }
00263
00264
00265 u_int OggVorbisReader::getCursor(){ return implement_->getCursor(); }
00266
00267
00268 bool OggVorbisReader::readHeader(){ return implement_->readHeader(); }
00269
00270
00271 int OggVorbisReader::read(void* buffer, u_int size){
00272 return implement_->read(buffer, size);
00273 }
00274
00275 }
00276