00001
00002 #include "Core/precomp.h"
00003
00004 #include <iostream>
00005 #include "API/Core/System/cl_assert.h"
00006
00007 #include "soundbuffer_stream_dx.h"
00008
00009 #define STREAM_BUFFER_LENGTH_SECS 2
00010
00011 CL_CardSoundBufferPlaybackStream_DX::CL_CardSoundBufferPlaybackStream_DX(
00012 CL_SoundCard_DX *card,
00013 CL_SoundBuffer_Generic_Stream *parent_buffer)
00014 {
00015 buffer = parent_buffer;
00016 parent_card = card;
00017 provider = parent_buffer->get_stream_provider();
00018 provider_session = provider->begin_session();
00019
00020 int num_channels;
00021 int bps;
00022
00023 switch (provider_session->get_format())
00024 {
00025 case sf_8bit_signed:
00026 num_channels = 1;
00027 bps = 8;
00028 break;
00029 case sf_8bit_signed_stereo:
00030 num_channels = 2;
00031 bps = 8;
00032 break;
00033 case sf_16bit_signed:
00034 num_channels = 1;
00035 bps = 16;
00036 break;
00037 case sf_16bit_signed_stereo:
00038 num_channels = 2;
00039 bps = 16;
00040 break;
00041 }
00042
00043 WAVEFORMATEX format;
00044 format.wFormatTag = WAVE_FORMAT_PCM;
00045 format.nChannels = num_channels;
00046 format.nSamplesPerSec = provider_session->get_frequency();
00047 format.wBitsPerSample = bps;
00048 format.nBlockAlign = format.wBitsPerSample * format.nChannels / 8;
00049 format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign;
00050 format.cbSize = 0;
00051
00052 DSBUFFERDESC desc;
00053 desc.dwSize = sizeof(DSBUFFERDESC);
00054 desc.dwFlags = DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY;
00055
00056
00057 desc.dwBufferBytes = format.nAvgBytesPerSec*STREAM_BUFFER_LENGTH_SECS;
00058 desc.dwReserved = 0;
00059 desc.lpwfxFormat = &format;
00060
00061 size_buffer = desc.dwBufferBytes;
00062 secure_distance = int(float(format.nAvgBytesPerSec) / 10);
00063 fill_position = 0;
00064
00065 soundbuffer = NULL;
00066
00067 if (parent_card->soundcard != NULL)
00068 {
00069 HRESULT err = parent_card->soundcard->CreateSoundBuffer(&desc, &soundbuffer, NULL);
00070 }
00071
00072 sound_is_playing = false;
00073 empty_pos = -1;
00074
00075 update_buffer();
00076 }
00077
00078 CL_CardSoundBufferPlaybackStream_DX::~CL_CardSoundBufferPlaybackStream_DX()
00079 {
00080 provider->end_session(provider_session);
00081 if (soundbuffer != NULL) soundbuffer->Release();
00082 }
00083
00084 int CL_CardSoundBufferPlaybackStream_DX::get_position()
00085 {
00086 return -1;
00087 }
00088
00089 float CL_CardSoundBufferPlaybackStream_DX::get_position_relative()
00090 {
00091 return -1;
00092 }
00093
00094 bool CL_CardSoundBufferPlaybackStream_DX::set_position(int new_pos)
00095 {
00096 return false;
00097 }
00098
00099
00100 bool CL_CardSoundBufferPlaybackStream_DX::set_position_relative(float new_pos)
00101 {
00102 return false;
00103 }
00104
00105 int CL_CardSoundBufferPlaybackStream_DX::get_length()
00106 {
00107 return -1;
00108 }
00109
00110 CL_SoundBuffer_Generic *CL_CardSoundBufferPlaybackStream_DX::get_owner()
00111 {
00112 return buffer;
00113 }
00114
00115 int CL_CardSoundBufferPlaybackStream_DX::get_frequency()
00116 {
00117 if (soundbuffer == NULL) return -1;
00118
00119 DWORD ret;
00120 soundbuffer->GetFrequency(&ret);
00121 return ret;
00122 }
00123
00124 bool CL_CardSoundBufferPlaybackStream_DX::set_frequency(int new_freq)
00125 {
00126 if (soundbuffer == NULL) return false;
00127
00128 HRESULT err = soundbuffer->SetFrequency(new_freq);
00129 if (err != DS_OK) { return false; }
00130
00131 return true;
00132 }
00133
00134 float CL_CardSoundBufferPlaybackStream_DX::get_volume()
00135 {
00136 if (soundbuffer == NULL) return -1;
00137
00138 long temp;
00139 soundbuffer->GetVolume(&temp);
00140
00141 return pow(10, temp/20);
00142 }
00143
00144 bool CL_CardSoundBufferPlaybackStream_DX::set_volume(float new_volume)
00145 {
00146 if (soundbuffer == NULL) return false;
00147
00148 if (new_volume == 0) soundbuffer->SetVolume(DSBVOLUME_MIN);
00149 else soundbuffer->SetVolume(100*20*log10(new_volume));
00150
00151 return true;
00152 }
00153
00154 float CL_CardSoundBufferPlaybackStream_DX::get_pan()
00155 {
00156 if (soundbuffer == NULL) return -1;
00157
00158 long ret;
00159 soundbuffer->GetPan(&ret);
00160
00161 return ret;
00162 }
00163
00164 bool CL_CardSoundBufferPlaybackStream_DX::set_pan(float new_pan)
00165 {
00166 if (soundbuffer == NULL) return false;
00167
00168 if (new_pan < 0)
00169 soundbuffer->SetPan(DSBPAN_CENTER-DSBPAN_LEFT*new_pan);
00170 else
00171 soundbuffer->SetPan(DSBPAN_CENTER+DSBPAN_RIGHT*new_pan);
00172
00173 return true;
00174 }
00175
00176 void CL_CardSoundBufferPlaybackStream_DX::play()
00177 {
00178 if (soundbuffer == NULL) return;
00179
00180 soundbuffer->SetCurrentPosition(0);
00181 soundbuffer->Play(0, 0, DSBPLAY_LOOPING);
00182 sound_is_playing = true;
00183 }
00184
00185 void CL_CardSoundBufferPlaybackStream_DX::stop()
00186 {
00187 if (soundbuffer == NULL) return;
00188
00189 soundbuffer->Stop();
00190 sound_is_playing = false;
00191 }
00192
00193 bool CL_CardSoundBufferPlaybackStream_DX::is_playing()
00194 {
00195 if (soundbuffer == NULL) return false;
00196
00197 DWORD status;
00198 soundbuffer->GetStatus(&status);
00199
00200 return (status & DSBSTATUS_PLAYING) == DSBSTATUS_PLAYING;
00201 }
00202
00203 void CL_CardSoundBufferPlaybackStream_DX::set_looping(bool loop)
00204 {
00205 if (soundbuffer == NULL) return;
00206 }
00207
00208 char *get_dsounderr(HRESULT);
00209 void CL_CardSoundBufferPlaybackStream_DX::update_buffer()
00210 {
00211 if (soundbuffer == NULL) return;
00212
00213 unsigned char *ptr1, *ptr2;
00214 DWORD size1, size2;
00215 DWORD written1 = 0;
00216 DWORD written2 = 0;
00217 DWORD playpos, writepos;
00218 HRESULT err;
00219
00220 err = soundbuffer->GetCurrentPosition(&playpos, &writepos);
00221 cl_assert(err == DS_OK);
00222
00223 if (playpos > fill_position) fill_length = playpos - fill_position - secure_distance;
00224 else fill_length = (size_buffer-fill_position) + playpos - secure_distance;
00225
00226 if (fill_length > secure_distance)
00227 {
00228 err = soundbuffer->Lock(fill_position, fill_length, (void **) &ptr1, &size1, (void **) &ptr2, &size2, 0);
00229 if (err != DS_OK)
00230 {
00231 std::cout << "SHIT! We are going down!..." << std::endl;
00232 std::cout << "fill_position: " << fill_position << ", fill_length: " << fill_length << std::endl;
00233 std::cout << "size_buffer: " << size_buffer << ", playpos: " << playpos;
00234 std::cout << ", writepos: " << writepos << std::endl;
00235 char *error = get_dsounderr(err);
00236 std::cout << error << std::endl;
00237 }
00238 cl_assert(err == DS_OK);
00239
00240 written1 = provider_session->get_data(ptr1, size1);
00241 if (provider_session->get_format() == sf_8bit_signed)
00242 {
00243 for (DWORD i=0;i<written1;i++) ptr1[i] = (unsigned char) (short(ptr1[i])+128);
00244 }
00245 if (written1 == size1)
00246 {
00247 written2 = provider_session->get_data(ptr2, size2);
00248 if (provider_session->get_format() == sf_8bit_signed)
00249 {
00250 for (DWORD i=0;i<written2;i++) ptr2[i] = (unsigned char) (short(ptr2[i])+128);
00251 }
00252 if (written2 != size2)
00253 {
00254 if (provider_session->get_format() == sf_8bit_signed) memset(&ptr2[written2], 128, size2-written2);
00255 else memset(&ptr2[written2], 0, size2-written2);
00256 written2 = size2;
00257 }
00258 }
00259 else
00260 {
00261 if (provider_session->get_format() == sf_8bit_signed)
00262 {
00263 memset(&ptr1[written1], 128, size1-written1);
00264 written1 = size1;
00265 memset(ptr2, 128, size2);
00266 written2 = size2;
00267 }
00268 else
00269 {
00270 memset(&ptr1[written1], 0, size1-written1);
00271 written1 = size1;
00272 memset(ptr2, 0, size2);
00273 written2 = size2;
00274 }
00275 }
00276
00277 soundbuffer->Unlock(ptr1, written1, ptr2, written2);
00278
00279 fill_position += fill_length;
00280 if (fill_position >= size_buffer) fill_position -= size_buffer;
00281
00282 if (provider_session->eof() && empty_pos == -1)
00283 {
00284 empty_pos = fill_position;
00285 wait_for_play_wrap = playpos >= empty_pos;
00286 }
00287
00288 if (empty_pos != -1)
00289 {
00290 if (wait_for_play_wrap && playpos < empty_pos) wait_for_play_wrap = false;
00291 if (!wait_for_play_wrap && playpos >= empty_pos)
00292 {
00293 soundbuffer->Stop();
00294 sound_is_playing = false;
00295 }
00296 }
00297 }
00298 }
00299
00300 void CL_CardSoundBufferPlaybackStream_DX::keep_alive()
00301 {
00302 if (sound_is_playing)
00303 {
00304 update_buffer();
00305 }
00306 }