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/Utility/StreamPlayer.h"
00027 #include "Sound/System/SoundBuffer.h"
00028 #include "Sound/Reader/SoundReader.h"
00029 #include "Core/Thread/SynchronizedBlock.h"
00030
00031 namespace Lamp{
00032
00033
00034
00035 StreamPlayer::StreamPlayer() :
00036 directSoundNotify_(NULL), soundBuffer_(NULL), soundReader_(NULL),
00037 cursor_(0), loopCursor_(0), initialized_(false){
00038 for(int i = 0; i < eventCount_; i++){ event_[i] = NULL; }
00039 }
00040
00041
00042 StreamPlayer::~StreamPlayer(){
00043 soundBuffer_->stop();
00044
00045 requestStop();
00046 ::SetEvent(event_[2]);
00047 join();
00048 for(int i = 0; i < eventCount_; i++){
00049 if(event_[i] != NULL){ CloseHandle(event_[i]); }
00050 }
00051 SafeRelease(directSoundNotify_);
00052 }
00053
00054
00055 bool StreamPlayer::initialize(
00056 SoundBuffer* soundBuffer, SoundReader* soundReader){
00057 if(initialized_){ Assert(false); return true; }
00058 soundBuffer_ = soundBuffer;
00059 soundReader_ = soundReader;
00060 Assert((soundBuffer_ != NULL) && (soundReader_ != NULL));
00061
00062 if(DirectXFailed(soundBuffer_->getSoundBuffer()->QueryInterface(
00063 DirectSoundNotifyInterfaceID, (void**)&directSoundNotify_))){
00064 ErrorOut("StreamPlayer::initialize() "
00065 "通知インターフェースの取得に失敗しました。");
00066 return false;
00067 }
00068
00069 for(int i = 0; i < eventCount_; i++){
00070 event_[i] = ::CreateEvent(NULL, false, false, NULL);
00071 }
00072 DSBPOSITIONNOTIFY cursorNotify[eventCount_];
00073 cursorNotify[0].dwOffset = 0;
00074 cursorNotify[0].hEventNotify = event_[0];
00075 cursorNotify[1].dwOffset = soundBuffer_->getBufferSize() / 2;
00076 cursorNotify[1].hEventNotify = event_[1];
00077 cursorNotify[2].dwOffset = DSBPN_OFFSETSTOP;
00078 cursorNotify[2].hEventNotify = event_[2];
00079 if(DirectXFailed(directSoundNotify_->SetNotificationPositions(
00080 eventCount_, cursorNotify))){
00081 ErrorOut("StreamPlayer::initialize() "
00082 "通知イベントの設定に失敗しました。");
00083 }
00084
00085 reset();
00086 initialized_ = true;
00087
00088 start();
00089 return true;
00090 }
00091
00092
00093 void StreamPlayer::reset(){
00094 bool result = writeStream(0);
00095 Assert(result);
00096 }
00097
00098
00099 void StreamPlayer::run(Thread* thread){
00100 Assert(initialized_);
00101 while(!isStopRequested()){
00102 u_long flag = ::WaitForMultipleObjects(
00103 eventCount_, event_, false, INFINITE);
00104 switch(flag){
00105 case WAIT_OBJECT_0 + 0:
00106
00107 while((!isStopRequested()) && (!writeStream(1))){ yield(); }
00108 break;
00109 case WAIT_OBJECT_0 + 1:
00110
00111 while((!isStopRequested()) && (!writeStream(0))){ yield(); }
00112 break;
00113 case WAIT_OBJECT_0 + 2:
00114 break;
00115 }
00116 }
00117 }
00118
00119
00120 bool StreamPlayer::writeStream(int offset){
00121 u_int size = soundBuffer_->getSize();
00122 bool isLoop = soundBuffer_->isLoop();
00123 u_int writeSize = soundBuffer_->getBufferSize() / 2;
00124 u_int writeOffset = writeSize * (offset & 1);
00125
00126 if((!isLoop) && (cursor_ == size)){
00127 soundBuffer_->stop();
00128 return true;
00129 }
00130
00131 SoundBuffer::Lock& lock = soundBuffer_->lock(writeOffset, writeSize);
00132 if(!lock.isValid()){ return false; }
00133
00134 Assert((lock.getAddress0() != NULL) && (lock.getSize0() == writeSize));
00135 Assert((lock.getAddress1() == NULL) && (lock.getSize1() == 0));
00136
00137 u_int cursor, loopCursor;
00138 {
00139 SynchronizedBlock synchronizedBlock(this);
00140 cursor = cursor_;
00141 loopCursor = loopCursor_;
00142 cursor_ += writeSize;
00143
00144 if(cursor_ > size){
00145 if(isLoop){ cursor_ = loopCursor + (cursor_ - size); }
00146 else{ cursor_ = size; }
00147 }
00148 }
00149 Assert(soundReader_->getCursor() == cursor);
00150
00151 int preWriteSize = writeSize;
00152 int postWriteSize = (cursor + writeSize) - size;
00153 if(postWriteSize > 0){ preWriteSize -= postWriteSize; }
00154 int result = soundReader_->read(lock.getAddress0(), preWriteSize);
00155 Assert(result == preWriteSize);
00156
00157 char* postWriteAddress = (((char*)lock.getAddress0()) + preWriteSize);
00158 if(postWriteSize > 0){
00159 if(isLoop){
00160
00161 soundReader_->setCursor(loopCursor);
00162 result = soundReader_->read(postWriteAddress, postWriteSize);
00163 Assert(result == postWriteSize);
00164 }else{
00165
00166 u_char value = 0;
00167 if(soundBuffer_->getBit() == 8){ value = 128; }
00168 ::memset(postWriteAddress, 0, postWriteSize);
00169 }
00170 }
00171 soundBuffer_->unlock();
00172 return true;
00173 }
00174
00175
00176
00177
00178 void StreamPlayer::setCursor(u_int cursor){
00179 Assert(cursor <= soundBuffer_->getSize());
00180
00181 u_int fixedCursor =
00182 cursor - (cursor % soundBuffer_->getOneSampleBytes());
00183 {
00184 SynchronizedBlock synchronizedBlock(this);
00185 cursor_ = fixedCursor;
00186 soundReader_->setCursor(cursor_);
00187 }
00188 }
00189
00190
00191
00192
00193 void StreamPlayer::setLoopCursor(u_int loopCursor){
00194 Assert(loopCursor <= soundBuffer_->getSize());
00195
00196 u_int fixedLoopCursor =
00197 loopCursor - (loopCursor % soundBuffer_->getOneSampleBytes());
00198 {
00199 SynchronizedBlock synchronizedBlock(this);
00200 loopCursor_ = fixedLoopCursor;
00201 }
00202 }
00203
00204 }
00205