「C言語/C++/spticdda」の編集履歴(バックアップ)一覧はこちら

C言語/C++/spticdda - (2012/10/14 (日) 22:20:01) の1つ前との変更点

追加された行は緑色になります。

削除された行は赤色になります。

|開発環境|Microsoft Visual C++ 2010 Express (SP1)| |実行環境|Microsoft Windows XP Home Edition (SP3)| |プロジェクトの種類|Win32 プロジェクト| |プロジェクト名|spticdda| |アプリケーションの種類|Windows アプリケーション| |追加のオプション|空のプロジェクト| |文字セット|Unicode| Microsoft DirectX SDK (February 2010) Windows Driver Kit Version 7.1.0 作りかけ。 参考 -[[DirectSound>http://www2.muroran-it.ac.jp/circle/mpc/front/old1/program/windows/spti_cdda/spti06.html]] -[[wavファイルから音を抽出>http://marupeke296.com/DSSMP_No2_GetSoundFromWave.html]] spticdda.cpp #highlight(cpp){{ /* [構成プロパティ]-[VC++ ディレクトリ] [インクルード ディレクトリ] C:\Program Files\Microsoft DirectX SDK (February 2010)\Include C:\WinDDK\7600.16385.1\src\storage\tools\spti [ライブラリ ディレクトリ] C:\Program Files\Microsoft DirectX SDK (February 2010)\Lib\x86 Unicode文字セット */ #pragma comment(lib, "dsound.lib") #pragma comment(lib, "dxguid.lib") //#include <Windows.h> #include <tchar.h> #include <dsound.h> #include <ntddscsi.h> #include <spti.h> #include <stddef.h> #include "resource.h" #define REVWORD(w) (((w<<8)&0xff00)|((w>>8)&0xff)) #define REVDWORD(dw) (((dw<<24)&0xff000000)|((dw<<8)&0xff0000)|((dw>>8)&0xff00)|((dw>>24)&0xff)) #define COMRELEASE(obj) if(obj){obj->Release();obj=NULL;} #define NOTIFYEVENTS 2 #define CDDASECT 2352 #define READSECT 15 struct READTOC { WORD wLen; BYTE byStartTrack; BYTE byEndTrack; struct TRACKDESC { BYTE d0; BYTE data; BYTE byTrack; BYTE d1; DWORD dwLBA; } td[100]; }; // 関数プロトタイプ宣言 INT_PTR CALLBACK MainDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); int Play(TCHAR cDrive, UINT uTrack, HWND hWnd); int ReadToc(TCHAR cDrive, UINT uTrack); int InitDirectSound(HWND hWnd); int ReadBuf(DWORD dwStartOffset, DWORD dwWriteSize); DWORD ExecCommand(HANDLE hDev, PUCHAR pucCdb, UCHAR ucCdbLen, PVOID pvData, ULONG ulDataLen); // 外部変数構造体 static struct { BOOL bPlay; // CD-DA HANDLE hDev; DWORD dwStartAddr; DWORD dwEndAddr; DWORD dwLBA; // DirectSound LPDIRECTSOUND8 pDS; LPDIRECTSOUNDBUFFER pPri; LPDIRECTSOUNDBUFFER pSec; LPDIRECTSOUNDNOTIFY pNotify; HANDLE hEvent[NOTIFYEVENTS]; DSBPOSITIONNOTIFY dspn[NOTIFYEVENTS]; DWORD dwBufferBytes; DWORD dwEoe; } g; //============================================================================== int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int) { DialogBox(hInstance, MAKEINTRESOURCE(IDD_MAIN), NULL, MainDlgProc); return 0; } //------------------------------------------------------------------------------ INT_PTR CALLBACK MainDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { INT_PTR nRet = TRUE; // メッセージを処理した switch (uMsg) { case WM_COMMAND: switch (LOWORD(wParam)) { case IDC_PLAY: if (g.bPlay) { g.bPlay = FALSE; break; } g.bPlay = TRUE; Play(_T('e'), 1, hDlg); break; case IDC_EXIT: if (g.bPlay == FALSE) { SendMessage(hDlg, WM_CLOSE, 0, 0); } break; } break; case WM_CLOSE: EndDialog(hDlg, IDOK); break; default: nRet = FALSE; // メッセージを処理しなかった } return nRet; } //------------------------------------------------------------------------------ int Play(TCHAR cDrive, UINT uTrack, HWND hWnd) { int iRet = -1; // 失敗 // TOCの読み込み if (ReadToc(cDrive, uTrack)) { goto Exit; } // DirectSoundの準備 if (InitDirectSound(hWnd)) { goto Exit; } // 再生 g.dwLBA = g.dwStartAddr; g.dwEoe = -1; if (ReadBuf(0, g.dwBufferBytes)) { goto Exit; } HRESULT hr; hr = g.pSec->SetCurrentPosition(0); hr = g.pSec->Play(0, 0, DSBPLAY_LOOPING); DWORD dwEventOffset = WaitForMultipleObjects(NOTIFYEVENTS, g.hEvent, FALSE, INFINITE); while (g.bPlay) { dwEventOffset = WaitForMultipleObjects(NOTIFYEVENTS, g.hEvent, FALSE, INFINITE); dwEventOffset -= WAIT_OBJECT_0; if (dwEventOffset == g.dwEoe) { break; } if (g.dwEoe < NOTIFYEVENTS) { continue; } DWORD dwStartOffset; DWORD dwWriteSize; if (dwEventOffset) { dwStartOffset = g.dspn[dwEventOffset-1].dwOffset; dwWriteSize = g.dspn[dwEventOffset].dwOffset - dwStartOffset; } else { dwStartOffset = g.dspn[NOTIFYEVENTS-1].dwOffset; dwWriteSize = g.dwBufferBytes - dwStartOffset; } if (ReadBuf(dwStartOffset, dwWriteSize)) { goto Exit; } if (g.dwEndAddr <= g.dwLBA) { g.dwEoe = dwEventOffset; } // メッセージ MSG msg; while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } } hr = g.pSec->Stop(); iRet = 0; Exit: COMRELEASE(g.pNotify); COMRELEASE(g.pSec); COMRELEASE(g.pPri); COMRELEASE(g.pDS); CloseHandle(g.hDev); return iRet; } //------------------------------------------------------------------------------ int ReadToc(TCHAR cDrv, UINT uTrack) { // デバイスのオープン TCHAR szDev[] = _T("\\\\.\\@:"); szDev[4] = cDrv; g.hDev = CreateFile(szDev, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (g.hDev == INVALID_HANDLE_VALUE) { return -1; } // TOCの読み込み BYTE byBuf[sizeof (READTOC) + 0xf]; // パラグラフ境界 READTOC *ptoc = (READTOC *)(((UINT_PTR)byBuf + 0xf) & ~0xf); UCHAR ucCdb[16]; DWORD dw; ZeroMemory(ptoc, sizeof *ptoc); ZeroMemory(ucCdb, sizeof ucCdb); ucCdb[0] = SCSIOP_READ_TOC; ucCdb[6] = 1; *(PWORD)(ucCdb + 7) = REVWORD(sizeof *ptoc); dw = ExecCommand(g.hDev, ucCdb, 10, ptoc, sizeof *ptoc); if (dw == 0) { return -1; } // トラックチェック if (ptoc->td[uTrack-1].data & 0x04) { // データトラック return -1; } // トラックLBA g.dwStartAddr = REVDWORD(ptoc->td[uTrack-1].dwLBA); g.dwEndAddr = REVDWORD(ptoc->td[uTrack].dwLBA) - 1; DWORD dwLen = g.dwEndAddr - g.dwStartAddr + 1; return 0; } //------------------------------------------------------------------------------ int InitDirectSound(HWND hWnd) { HRESULT hr; //---------------------------------------------------------------------- // DirectSoundの初期化 hr = DirectSoundCreate8(&DSDEVID_DefaultPlayback, &g.pDS, NULL); if (FAILED(hr)) { return -1; } // 協調レベルの設定 hr = g.pDS->SetCooperativeLevel(hWnd, DSSCL_PRIORITY); if (FAILED(hr)) { return -1; } //---------------------------------------------------------------------- DSBUFFERDESC bd; WAVEFORMATEX wfx; ZeroMemory(&wfx, sizeof wfx); wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.nChannels = 2; wfx.nSamplesPerSec = 44100; wfx.nAvgBytesPerSec = 44100 * 2 * 2; wfx.nBlockAlign = 2 * 2; wfx.wBitsPerSample = 16; // プライマリバッファの作成 ZeroMemory(&bd, sizeof bd); bd.dwSize = sizeof bd; bd.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLPAN; hr = g.pDS->CreateSoundBuffer(&bd, &g.pPri, NULL); if (FAILED(hr)) { return -1; } // プライマリバッファのフォーマット指定 hr = g.pPri->SetFormat(&wfx); if (FAILED(hr)) { return -1; } // セカンダリバッファの作成 ZeroMemory(&bd, sizeof bd); bd.dwSize = sizeof bd; bd.lpwfxFormat = &wfx; bd.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_GLOBALFOCUS; bd.dwBufferBytes = 44100 * 2 * 2 * 2; // 2秒 hr = g.pDS->CreateSoundBuffer(&bd, &g.pSec, NULL); if (FAILED(hr)) { return -1; } g.dwBufferBytes = bd.dwBufferBytes; //---------------------------------------------------------------------- // イベント hr = g.pSec->QueryInterface(IID_IDirectSoundNotify, (LPVOID *)&g.pNotify); if (FAILED(hr)) { return -1; } for (int n = 0; n < NOTIFYEVENTS; n++) { g.hEvent[n] = CreateEvent(NULL, FALSE, FALSE, NULL); // CloseHandle g.dspn[n].dwOffset = (n * bd.dwBufferBytes / NOTIFYEVENTS); g.dspn[n].hEventNotify = g.hEvent[n]; } hr = g.pNotify->SetNotificationPositions(NOTIFYEVENTS, g.dspn); if (FAILED(hr)) { return -1; } return 0; } //------------------------------------------------------------------------------ // セカンダリバッファへの読み込み int ReadBuf(DWORD dwOffset, DWORD dwBytes) { BYTE byBuf[CDDASECT * READSECT + 0xf]; // パラグラフ境界 PBYTE pbyBuf = (PBYTE)(((UINT_PTR)byBuf + 0xf) & ~0xf); UCHAR ucCdb[16]; ZeroMemory(pbyBuf, CDDASECT * READSECT); ZeroMemory(ucCdb, sizeof ucCdb); ucCdb[0] = 0xbe; // SCSIOP_READ_CD ucCdb[9] = 0x10; // IDirectSoundBuffer LPVOID pvAudioPtr[2]; DWORD dwAudioBytes[2]; HRESULT hr; hr = g.pSec->Lock(dwOffset, dwBytes, &pvAudioPtr[0], &dwAudioBytes[0], &pvAudioPtr[1], &dwAudioBytes[1], 0); DWORD dwReadSect = dwBytes / CDDASECT; for (DWORD dwSect = 0; (dwSect < dwReadSect) && (g.dwLBA < g.dwEndAddr); ) { DWORD dwReadSize; if (g.dwLBA + READSECT > g.dwEndAddr) { dwReadSize = g.dwEndAddr - g.dwLBA; g.dwEoe = 0; } else { dwReadSize = dwReadSect - dwSect; if (READSECT < dwReadSize) { dwReadSize = READSECT; } } *(PDWORD)(ucCdb + 2) = REVDWORD(g.dwLBA); ucCdb[8] = (UCHAR)dwReadSize; DWORD dwr = ExecCommand(g.hDev, ucCdb, 12, pbyBuf, CDDASECT * READSECT); if (dwr == 0) { return -1; } memcpy_s((PBYTE)pvAudioPtr[0] + CDDASECT * dwSect, dwAudioBytes[0], // 注意 pbyBuf, CDDASECT * dwReadSize); dwSect += dwReadSize; g.dwLBA += dwReadSize; } hr = g.pSec->Unlock(pvAudioPtr[0], dwAudioBytes[0], pvAudioPtr[1], dwAudioBytes[1]); return 0; } //------------------------------------------------------------------------------ DWORD ExecCommand(HANDLE hDevice, PUCHAR pucCdb, UCHAR ucCdbLen, PVOID pvData, ULONG ulDataLen) { SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER swb; DWORD dwBytesReturned; BOOL br; ZeroMemory(&swb, sizeof swb); swb.sptd.Length = sizeof swb.sptd; // swb.sptd.CdbLength = ucCdbLen; swb.sptd.SenseInfoLength = sizeof swb.ucSenseBuf; swb.sptd.DataIn = SCSI_IOCTL_DATA_IN; swb.sptd.DataTransferLength = ulDataLen; swb.sptd.TimeOutValue = 10; // 秒 swb.sptd.DataBuffer = pvData; swb.sptd.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, ucSenseBuf); memcpy_s(&swb.sptd.Cdb, sizeof swb.sptd.Cdb, pucCdb, ucCdbLen); br = DeviceIoControl( hDevice, IOCTL_SCSI_PASS_THROUGH_DIRECT, &swb, sizeof swb, // In &swb, sizeof swb, // Out &dwBytesReturned, NULL); if (br == FALSE) { return 0; } return dwBytesReturned; } }} resource.h #highlight(c){{ #define IDD_MAIN 100 #define IDC_STATIC -1 #define IDC_EXIT 1000 #define IDC_DEVICELIST 1001 #define IDC_TRACKLIST 1002 #define IDC_PLAY 1003 }} spticdda.rc #highlight(c){{ // resource script #include <windows.h> #include "resource.h" IDD_MAIN DIALOGEX 100, 100, 159, 53 STYLE WS_POPUPWINDOW | WS_MINIMIZEBOX EXSTYLE WS_EX_APPWINDOW CAPTION "spticdda" FONT 9, "MS Pゴシック" BEGIN DEFPUSHBUTTON "終了",IDC_EXIT,111,37,46,14 LTEXT "デバイス",IDC_STATIC,2,3,27,12,SS_CENTERIMAGE COMBOBOX IDC_DEVICELIST,29,3,128,215, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP LTEXT "トラック",IDC_STATIC,2,20,27,12,SS_CENTERIMAGE COMBOBOX IDC_TRACKLIST,29,20,128,230, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP PUSHBUTTON "再生",IDC_PLAY,60,37,46,14 END }}
|開発環境|Microsoft Visual C++ 2010 Express (SP1)| |実行環境|Microsoft Windows XP Home Edition (SP3)| |プロジェクトの種類|Win32 プロジェクト| |プロジェクト名|spticdda| |アプリケーションの種類|Windows アプリケーション| |追加のオプション|空のプロジェクト| |文字セット|Unicode| Microsoft DirectX SDK (February 2010) Windows Driver Kit Version 7.1.0 参考 -[[DirectSound>http://www2.muroran-it.ac.jp/circle/mpc/front/old1/program/windows/spti_cdda/spti06.html]] -[[wavファイルから音を抽出>http://marupeke296.com/DSSMP_No2_GetSoundFromWave.html]] spticdda.cpp #highlight(cpp){{ /* [構成プロパティ]-[VC++ ディレクトリ] [インクルード ディレクトリ] C:\Program Files\Microsoft DirectX SDK (February 2010)\Include C:\WinDDK\7600.16385.1\src\storage\tools\spti [ライブラリ ディレクトリ] C:\Program Files\Microsoft DirectX SDK (February 2010)\Lib\x86 Unicode文字セット */ #pragma comment(lib, "dsound.lib") #pragma comment(lib, "dxguid.lib") //#include <Windows.h> #include <tchar.h> #include <dsound.h> #include <ntddscsi.h> #include <spti.h> #include <stddef.h> #include "resource.h" #define REVWORD(w) (((w<<8)&0xff00)|((w>>8)&0xff)) #define REVDWORD(dw) (((dw<<24)&0xff000000)|((dw<<8)&0xff0000)|((dw>>8)&0xff00)|((dw>>24)&0xff)) #define COMRELEASE(obj) if(obj){obj->Release();obj=NULL;} #define NOTIFYEVENTS 2 #define CDDASECT 2352 #define READSECT 15 struct READTOC { WORD wLen; BYTE byStartTrack; BYTE byEndTrack; struct TRACKDESC { BYTE d0; BYTE data; BYTE byTrack; BYTE d1; DWORD dwLBA; } td[100]; }; // 関数プロトタイプ宣言 INT_PTR CALLBACK MainDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); void OnInitDialog(HWND hDlg); int TrackList(HWND hWnd, TCHAR cDrv); int ReadToc(TCHAR cDrv); void OnPlay(HWND hDlg); int Play(TCHAR cDrive, UINT uTrack, HWND hWnd); int InitDirectSound(HWND hWnd); int ReadBuf(DWORD dwStartOffset, DWORD dwWriteSize); DWORD ExecCommand(HANDLE hDev, PUCHAR pucCdb, UCHAR ucCdbLen, PVOID pvData, ULONG ulDataLen); // 外部変数構造体 static struct { BOOL bPlay; // CD-DA HANDLE hDev; BYTE byToc[sizeof(READTOC)+0xf]; READTOC *ptoc; DWORD dwStartAddr; DWORD dwEndAddr; DWORD dwLBA; // DirectSound LPDIRECTSOUND8 pDS; LPDIRECTSOUNDBUFFER pPri; LPDIRECTSOUNDBUFFER pSec; LPDIRECTSOUNDNOTIFY pNotify; HANDLE hEvent[NOTIFYEVENTS]; DSBPOSITIONNOTIFY dspn[NOTIFYEVENTS]; DWORD dwBufferBytes; DWORD dwEoe; } g; //============================================================================== int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int) { DialogBox(hInstance, MAKEINTRESOURCE(IDD_MAIN), NULL, MainDlgProc); return 0; } //------------------------------------------------------------------------------ INT_PTR CALLBACK MainDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { INT_PTR nRet = TRUE; // メッセージを処理した switch (uMsg) { case WM_COMMAND: switch (LOWORD(wParam)) { case IDC_DEVICELIST: { TCHAR szBuf[3+1]; HWND hWnd = GetDlgItem(hDlg, IDC_DEVICELIST); LRESULT lr = SendMessage(hWnd, CB_GETCURSEL, 0, 0); SendMessage(hWnd, CB_GETLBTEXT, lr, (LPARAM)szBuf); if (szBuf[0]) { TrackList(hDlg, szBuf[0]); } } break; case IDC_PLAY: if (g.bPlay) { g.bPlay = FALSE; break; } g.bPlay = TRUE; OnPlay(hDlg); g.bPlay = FALSE; break; case IDC_EXIT: if (g.bPlay == FALSE) { SendMessage(hDlg, WM_CLOSE, 0, 0); } break; } break; case WM_CLOSE: EndDialog(hDlg, 0); break; case WM_INITDIALOG: g.hDev = INVALID_HANDLE_VALUE; OnInitDialog(hDlg); break; case WM_DESTROY: if (g.hDev != INVALID_HANDLE_VALUE) { CloseHandle(g.hDev); } break; default: nRet = FALSE; // メッセージを処理しなかった } return nRet; } //------------------------------------------------------------------------------ void OnInitDialog(HWND hDlg) { TCHAR szBuf[26*4+1]; LPCTSTR pszDrv; HWND hWnd; DWORD dwr; UINT ur; // CD-ROMドライブ一覧 hWnd = GetDlgItem(hDlg, IDC_DEVICELIST); dwr = GetLogicalDriveStrings(_countof(szBuf) - 1, szBuf); for (pszDrv = szBuf; *pszDrv; pszDrv += 4) { ur = GetDriveType(pszDrv); if (ur == DRIVE_CDROM) { SendMessage(hWnd, CB_ADDSTRING, 0, (LPARAM)pszDrv); } } SendMessage(hWnd, CB_SETCURSEL, 0, 0); SendMessage(hWnd, CB_GETLBTEXT, 0, (LPARAM)szBuf); TrackList(hDlg, szBuf[0]); } //------------------------------------------------------------------------------ int TrackList(HWND hDlg, TCHAR cDrv) { TCHAR szBuf[64]; HWND hWnd; BYTE by; hWnd = GetDlgItem(hDlg, IDC_TRACKLIST); SendMessage(hWnd, CB_RESETCONTENT, 0, 0); if (ReadToc(cDrv)) { return -1; } for (by = 0; by < g.ptoc->byEndTrack; by++) { DWORD dwStartAddr = REVDWORD(g.ptoc->td[by].dwLBA); DWORD dwEndAddr = REVDWORD(g.ptoc->td[by+1].dwLBA) - 1; DWORD dwLen = dwEndAddr - dwStartAddr + 1; _stprintf_s(szBuf, _T("%2u, LBA[%6u-%6u], Len[%6u]"), by+1, dwStartAddr, dwEndAddr, dwLen); SendMessage(hWnd, CB_ADDSTRING, 0, (LPARAM)szBuf); } SendMessage(hWnd, CB_SETCURSEL, 0, 0); return 0; } //------------------------------------------------------------------------------ int ReadToc(TCHAR cDrv) { TCHAR szDev[] = _T("\\\\.\\@:"); UCHAR ucCdb[16]; DWORD dwr; // デバイスのオープン szDev[4] = cDrv; if (g.hDev != INVALID_HANDLE_VALUE) { CloseHandle(g.hDev); } g.hDev = CreateFile(szDev, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (g.hDev == INVALID_HANDLE_VALUE) { return -1; } // TOCの読み込み g.ptoc = (READTOC *)(((UINT_PTR)g.byToc + 0xf) & ~0xf); ZeroMemory(g.ptoc, sizeof *g.ptoc); ZeroMemory(ucCdb, sizeof ucCdb); ucCdb[0] = SCSIOP_READ_TOC; ucCdb[6] = 1; *(PWORD)(ucCdb + 7) = REVWORD(sizeof *g.ptoc); dwr = ExecCommand(g.hDev, ucCdb, 10, g.ptoc, sizeof *g.ptoc); if (dwr == 0) { return -1; } return 0; } //------------------------------------------------------------------------------ void OnPlay(HWND hDlg) { TCHAR szBuf[64]; TCHAR cDrive; UINT uTrack; HWND hWnd; LRESULT lr; // ドライブ hWnd = GetDlgItem(hDlg, IDC_DEVICELIST); lr = SendMessage(hWnd, CB_GETCURSEL, 0, 0); SendMessage(hWnd, CB_GETLBTEXT, lr, (LPARAM)szBuf); cDrive = szBuf[0]; if (!cDrive) { return; } // トラック hWnd = GetDlgItem(hDlg, IDC_TRACKLIST); lr = SendMessage(hWnd, CB_GETCURSEL, 0, 0); SendMessage(hWnd, CB_GETLBTEXT, lr, (LPARAM)szBuf); szBuf[2] = _T('\0'); uTrack = _ttoi(szBuf); if (99 < uTrack) { return; } Play(cDrive, uTrack, hDlg); } //------------------------------------------------------------------------------ int Play(TCHAR cDrive, UINT uTrack, HWND hWnd) { int iRet = -1; // 失敗 // トラックチェック if (g.ptoc->td[uTrack-1].data & 0x04) { // データトラック goto Exit; } // トラックLBA g.dwStartAddr = REVDWORD(g.ptoc->td[uTrack-1].dwLBA); g.dwEndAddr = REVDWORD(g.ptoc->td[uTrack].dwLBA) - 1; // DirectSoundの準備 if (InitDirectSound(hWnd)) { goto Exit; } // 再生 g.dwLBA = g.dwStartAddr; g.dwEoe = -1; if (ReadBuf(0, g.dwBufferBytes)) { goto Exit; } HRESULT hr; hr = g.pSec->SetCurrentPosition(0); hr = g.pSec->Play(0, 0, DSBPLAY_LOOPING); DWORD dwEventOffset = WaitForMultipleObjects(NOTIFYEVENTS, g.hEvent, FALSE, INFINITE); while (g.bPlay) { dwEventOffset = WaitForMultipleObjects(NOTIFYEVENTS, g.hEvent, FALSE, INFINITE); dwEventOffset -= WAIT_OBJECT_0; if (dwEventOffset == g.dwEoe) { break; } if (g.dwEoe < NOTIFYEVENTS) { continue; } DWORD dwStartOffset; DWORD dwWriteSize; if (dwEventOffset) { dwStartOffset = g.dspn[dwEventOffset-1].dwOffset; dwWriteSize = g.dspn[dwEventOffset].dwOffset - dwStartOffset; } else { dwStartOffset = g.dspn[NOTIFYEVENTS-1].dwOffset; dwWriteSize = g.dwBufferBytes - dwStartOffset; } if (ReadBuf(dwStartOffset, dwWriteSize)) { goto Exit; } if (g.dwEndAddr <= g.dwLBA) { g.dwEoe = dwEventOffset; } // メッセージ MSG msg; while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } } hr = g.pSec->Stop(); iRet = 0; Exit: COMRELEASE(g.pNotify); COMRELEASE(g.pSec); COMRELEASE(g.pPri); COMRELEASE(g.pDS); return iRet; } //------------------------------------------------------------------------------ int InitDirectSound(HWND hWnd) { HRESULT hr; //---------------------------------------------------------------------- // DirectSoundの初期化 hr = DirectSoundCreate8(&DSDEVID_DefaultPlayback, &g.pDS, NULL); if (FAILED(hr)) { return -1; } // 協調レベルの設定 hr = g.pDS->SetCooperativeLevel(hWnd, DSSCL_PRIORITY); if (FAILED(hr)) { return -1; } //---------------------------------------------------------------------- DSBUFFERDESC bd; WAVEFORMATEX wfx; ZeroMemory(&wfx, sizeof wfx); wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.nChannels = 2; wfx.nSamplesPerSec = 44100; wfx.nAvgBytesPerSec = 44100 * 2 * 2; wfx.nBlockAlign = 2 * 2; wfx.wBitsPerSample = 16; // プライマリバッファの作成 ZeroMemory(&bd, sizeof bd); bd.dwSize = sizeof bd; bd.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLPAN; hr = g.pDS->CreateSoundBuffer(&bd, &g.pPri, NULL); if (FAILED(hr)) { return -1; } // プライマリバッファのフォーマット指定 hr = g.pPri->SetFormat(&wfx); if (FAILED(hr)) { return -1; } // セカンダリバッファの作成 ZeroMemory(&bd, sizeof bd); bd.dwSize = sizeof bd; bd.lpwfxFormat = &wfx; bd.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_GLOBALFOCUS; bd.dwBufferBytes = 44100 * 2 * 2 * 2; // 2秒 hr = g.pDS->CreateSoundBuffer(&bd, &g.pSec, NULL); if (FAILED(hr)) { return -1; } g.dwBufferBytes = bd.dwBufferBytes; //---------------------------------------------------------------------- // イベント hr = g.pSec->QueryInterface(IID_IDirectSoundNotify, (LPVOID *)&g.pNotify); if (FAILED(hr)) { return -1; } for (int n = 0; n < NOTIFYEVENTS; n++) { g.hEvent[n] = CreateEvent(NULL, FALSE, FALSE, NULL); // CloseHandle g.dspn[n].dwOffset = (n * bd.dwBufferBytes / NOTIFYEVENTS); g.dspn[n].hEventNotify = g.hEvent[n]; } hr = g.pNotify->SetNotificationPositions(NOTIFYEVENTS, g.dspn); if (FAILED(hr)) { return -1; } return 0; } //------------------------------------------------------------------------------ // セカンダリバッファへの読み込み int ReadBuf(DWORD dwOffset, DWORD dwBytes) { BYTE byBuf[CDDASECT * READSECT + 0xf]; // パラグラフ境界 PBYTE pbyBuf = (PBYTE)(((UINT_PTR)byBuf + 0xf) & ~0xf); UCHAR ucCdb[16]; ZeroMemory(pbyBuf, CDDASECT * READSECT); ZeroMemory(ucCdb, sizeof ucCdb); ucCdb[0] = 0xbe; // SCSIOP_READ_CD ucCdb[9] = 0x10; // IDirectSoundBuffer LPVOID pvAudioPtr[2]; DWORD dwAudioBytes[2]; HRESULT hr; hr = g.pSec->Lock(dwOffset, dwBytes, &pvAudioPtr[0], &dwAudioBytes[0], &pvAudioPtr[1], &dwAudioBytes[1], 0); DWORD dwReadSect = dwBytes / CDDASECT; for (DWORD dwSect = 0; (dwSect < dwReadSect) && (g.dwLBA < g.dwEndAddr); ) { DWORD dwReadSize; if (g.dwLBA + READSECT > g.dwEndAddr) { dwReadSize = g.dwEndAddr - g.dwLBA; g.dwEoe = 0; } else { dwReadSize = dwReadSect - dwSect; if (READSECT < dwReadSize) { dwReadSize = READSECT; } } *(PDWORD)(ucCdb + 2) = REVDWORD(g.dwLBA); ucCdb[8] = (UCHAR)dwReadSize; DWORD dwr = ExecCommand(g.hDev, ucCdb, 12, pbyBuf, CDDASECT * READSECT); if (dwr == 0) { return -1; } DWORD dwPos = CDDASECT * dwSect; memcpy_s((PBYTE)pvAudioPtr[0] + dwPos, dwAudioBytes[0] - dwPos, pbyBuf, CDDASECT * dwReadSize); dwSect += dwReadSize; g.dwLBA += dwReadSize; } hr = g.pSec->Unlock(pvAudioPtr[0], dwAudioBytes[0], pvAudioPtr[1], dwAudioBytes[1]); return 0; } //------------------------------------------------------------------------------ DWORD ExecCommand(HANDLE hDevice, PUCHAR pucCdb, UCHAR ucCdbLen, PVOID pvData, ULONG ulDataLen) { SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER swb; DWORD dwBytesReturned; BOOL br; ZeroMemory(&swb, sizeof swb); swb.sptd.Length = sizeof swb.sptd; // swb.sptd.CdbLength = ucCdbLen; swb.sptd.SenseInfoLength = sizeof swb.ucSenseBuf; swb.sptd.DataIn = SCSI_IOCTL_DATA_IN; swb.sptd.DataTransferLength = ulDataLen; swb.sptd.TimeOutValue = 10; // 秒 swb.sptd.DataBuffer = pvData; swb.sptd.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, ucSenseBuf); memcpy_s(&swb.sptd.Cdb, sizeof swb.sptd.Cdb, pucCdb, ucCdbLen); br = DeviceIoControl( hDevice, IOCTL_SCSI_PASS_THROUGH_DIRECT, &swb, sizeof swb, // In &swb, sizeof swb, // Out &dwBytesReturned, NULL); if (br == FALSE) { return 0; } return dwBytesReturned; } }} resource.h #highlight(c){{ #define IDD_MAIN 100 #define IDC_STATIC -1 #define IDC_EXIT 1000 #define IDC_DEVICELIST 1001 #define IDC_TRACKLIST 1002 #define IDC_PLAY 1003 }} spticdda.rc #highlight(c){{ // resource script #include <windows.h> #include "resource.h" IDD_MAIN DIALOGEX 100, 100, 159, 53 STYLE WS_POPUPWINDOW | WS_MINIMIZEBOX EXSTYLE WS_EX_APPWINDOW CAPTION "spticdda" FONT 9, "MS Pゴシック" BEGIN DEFPUSHBUTTON "終了",IDC_EXIT,111,37,46,14 LTEXT "デバイス",IDC_STATIC,2,3,27,12,SS_CENTERIMAGE COMBOBOX IDC_DEVICELIST,29,3,128,215, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP LTEXT "トラック",IDC_STATIC,2,20,27,12,SS_CENTERIMAGE COMBOBOX IDC_TRACKLIST,29,20,128,230, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP PUSHBUTTON "再生",IDC_PLAY,60,37,46,14 END }}

表示オプション

横に並べて表示:
変化行の前後のみ表示: