// //
| 126 | |
| 127 | // // // |
| 128 | std::unique_ptr<CDSoundChannel> CDSound::OpenChannel(int SampleRate, int SampleSize, int Channels, int BufferLength, int Blocks) |
| 129 | { |
| 130 | // Open a new secondary buffer |
| 131 | // |
| 132 | |
| 133 | DSBPOSITIONNOTIFY dspn[MAX_BLOCKS]; |
| 134 | |
| 135 | ASSERT(Blocks > 1); |
| 136 | |
| 137 | if (!m_lpDirectSound) |
| 138 | return nullptr; |
| 139 | |
| 140 | // Adjust buffer length in case a buffer would end up in half samples |
| 141 | while ((SampleRate * BufferLength / (Blocks * 1000) != (double)SampleRate * BufferLength / (Blocks * 1000))) |
| 142 | ++BufferLength; |
| 143 | |
| 144 | auto pChannel = std::make_unique<CDSoundChannel>(); |
| 145 | |
| 146 | HANDLE hBufferEvent = CreateEventW(NULL, FALSE, FALSE, NULL); |
| 147 | |
| 148 | int SoundBufferSize = CalculateBufferLength(BufferLength, SampleRate, SampleSize, Channels); |
| 149 | int BlockSize = SoundBufferSize / Blocks; |
| 150 | |
| 151 | pChannel->m_iBufferLength = BufferLength; // in ms |
| 152 | pChannel->m_iSoundBufferSize = SoundBufferSize; // in bytes |
| 153 | pChannel->m_iBlockSize = BlockSize; // in bytes |
| 154 | pChannel->m_iBlocks = Blocks; |
| 155 | pChannel->m_iSampleSize = SampleSize; |
| 156 | pChannel->m_iSampleRate = SampleRate; |
| 157 | pChannel->m_iChannels = Channels; |
| 158 | |
| 159 | pChannel->m_iCurrentWriteBlock = 0; |
| 160 | pChannel->m_hWndTarget = m_hWndTarget; |
| 161 | pChannel->m_hEventList[0] = m_hNotificationHandle; |
| 162 | pChannel->m_hEventList[1] = hBufferEvent; |
| 163 | |
| 164 | WAVEFORMATEX wfx = { }; // // // |
| 165 | wfx.cbSize = sizeof(WAVEFORMATEX); |
| 166 | wfx.nChannels = Channels; |
| 167 | wfx.nSamplesPerSec = SampleRate; |
| 168 | wfx.wBitsPerSample = SampleSize; |
| 169 | wfx.nBlockAlign = wfx.nChannels * (wfx.wBitsPerSample / 8); |
| 170 | wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; |
| 171 | wfx.wFormatTag = WAVE_FORMAT_PCM; |
| 172 | |
| 173 | DSBUFFERDESC dsbd = {sizeof(DSBUFFERDESC)}; // // // |
| 174 | dsbd.dwBufferBytes = SoundBufferSize; |
| 175 | dsbd.dwFlags = DSBCAPS_LOCSOFTWARE | DSBCAPS_GLOBALFOCUS | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_GETCURRENTPOSITION2; |
| 176 | dsbd.lpwfxFormat = &wfx; |
| 177 | |
| 178 | if (FAILED(m_lpDirectSound->CreateSoundBuffer(&dsbd, &pChannel->m_lpDirectSoundBuffer, NULL))) |
| 179 | return nullptr; |
| 180 | |
| 181 | // Setup notifications |
| 182 | for (int i = 0; i < Blocks; ++i) { |
| 183 | dspn[i].dwOffset = i * BlockSize; |
| 184 | dspn[i].hEventNotify = hBufferEvent; |
| 185 | } |
no test coverage detected