WavePlayer
Visual C++ 2005 Express Edition
Windows Server 2003 SP1 Platform SDK
Windowsアプリケーション / 空のプロジェクト
WavePlayer.c
// マルチバイト文字セット // winmm.lib #include
#include
#include "WaveIO.h" #include "resource.h" // グローバル変数 static HWND g_hBtnPlay; static char g_acFile[_MAX_PATH] = ""; static WaveIO g_wioSrc; static WaveIO g_wioDst; static int g_iPlayFlag = 0; // プロトタイプ宣言 INT_PTR CALLBACK DialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); void OnBtnPlay(HWND hWnd); void OnDropFiles(HWND hWnd, WPARAM wParam); void OnInitDialog(HWND hDlg); void PlayStop(); int ConvertRate(WaveIO *pwioDst, const WaveIO *pwioSrc, HWND hWnd); int ConvertDec(WaveIO *pwioDst, const WaveIO *pwioSrc, int iDiv); int Convert150(WaveIO *pwioDst, const WaveIO *pwioSrc); int Convert200(WaveIO *pwioDst, const WaveIO *pwioSrc); int* GetWavLen(const WaveIO *pwioSrc); void SetFileInfo(HWND hWnd); int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { if (2 <= __argc) { if (WioRead(&g_wioSrc, __argv[1]) == 0) { strcpy_s(g_acFile, sizeof(g_acFile), __argv[1]); } } DialogBox(hInstance, MAKEINTRESOURCE(IDD_WAVEPLAYER), NULL, DialogProc); if (g_wioSrc.psWaveformData) { free(g_wioSrc.psWaveformData); } return 0; } INT_PTR CALLBACK DialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { BOOL bRetVal = TRUE; switch (uMsg) { case MM_WOM_DONE: PlayStop(); break; case WM_COMMAND: switch (LOWORD(wParam)) { case IDC_BTN_STOP: PlayStop(); break; case IDC_BTN_PLAY: OnBtnPlay(hDlg); break; } break; case WM_DROPFILES: OnDropFiles(hDlg, wParam); DragFinish((HDROP)wParam); break; case WM_INITDIALOG: OnInitDialog(hDlg); bRetVal = TRUE; // TRUEならデフォルトフォーカスを使用 break; case WM_CLOSE: PlayStop(); EndDialog(hDlg, IDOK); break; default: bRetVal = FALSE; } return bRetVal; } void OnBtnPlay(HWND hWnd) { int iRad; int iRet; int i; iRad = 0; for (i = IDC_RAD_1; i <= IDC_RAD_10; i++) { if (SendMessage(GetDlgItem(hWnd, i), BM_GETCHECK, 0, 0) == BST_CHECKED) { iRad = i; break; } } if (iRad == 0) { return; } switch (iRad) { case IDC_RAD_1: // 通常 iRet = ConvertRate(&g_wioDst, &g_wioSrc, GetDlgItem(hWnd, IDC_EDT_SRCRATE)); break; case IDC_RAD_2: // レート iRet = ConvertRate(&g_wioDst, &g_wioSrc, GetDlgItem(hWnd, IDC_EDT_DSTRATE)); break; case IDC_RAD_3: // 音程150% iRet = Convert150(&g_wioDst, &g_wioSrc); g_wioDst.dwSamplesPerSec = g_wioDst.dwSamplesPerSec * 3 / 2; break; case IDC_RAD_4: // 音程200% iRet = Convert200(&g_wioDst, &g_wioSrc); g_wioDst.dwSamplesPerSec = g_wioDst.dwSamplesPerSec * 2; break; case IDC_RAD_5: // 音程75% iRet = ConvertDec(&g_wioDst, &g_wioSrc, 2); g_wioDst.dwSamplesPerSec = g_wioDst.dwSamplesPerSec * 3 / 4; break; case IDC_RAD_6: // 音程50% iRet = ConvertDec(&g_wioDst, &g_wioSrc, 1); g_wioDst.dwSamplesPerSec = g_wioDst.dwSamplesPerSec / 2; break; case IDC_RAD_7: // 時間150% iRet = Convert150(&g_wioDst, &g_wioSrc); break; case IDC_RAD_8: // 時間200% iRet = Convert200(&g_wioDst, &g_wioSrc); break; case IDC_RAD_9: // 時間75% iRet = ConvertDec(&g_wioDst, &g_wioSrc, 2); break; case IDC_RAD_10: // 時間50% iRet = ConvertDec(&g_wioDst, &g_wioSrc, 1); break; default: return; } if (iRet) { return; } iRet = WioPlay(&g_wioDst, hWnd); if (iRet) { return; } g_iPlayFlag = 1; EnableWindow(g_hBtnPlay, FALSE); } void OnDropFiles(HWND hWnd, WPARAM wParam) { HDROP hDrop; char acFile[_MAX_PATH]; hDrop = (HDROP)wParam; DragQueryFile(hDrop, 0, acFile, sizeof(acFile)); g_acFile[0] = '\0'; if (WioRead(&g_wioSrc, acFile) == 0) { strcpy_s(g_acFile, sizeof(g_acFile), acFile); } SetFileInfo(hWnd); } void OnInitDialog(HWND hDlg) { RECT rcDesktop; RECT rcDialog; g_hBtnPlay = GetDlgItem(hDlg, IDC_BTN_PLAY); GetWindowRect(GetDesktopWindow(), &rcDesktop); GetWindowRect(hDlg, &rcDialog); SetWindowPos(hDlg, HWND_TOP, (rcDesktop.right - (rcDialog.right - rcDialog.left)) / 2, (rcDesktop.bottom - (rcDialog.bottom - rcDialog.top)) / 2, 0, 0, SWP_NOSIZE); SendMessage(GetDlgItem(hDlg, IDC_RAD_1), BM_SETCHECK, BST_CHECKED, 0); SetFileInfo(hDlg); } void PlayStop() { int iRet; if (g_iPlayFlag) { iRet = WioStop(&g_wioDst); free(g_wioDst.psWaveformData); g_iPlayFlag = 0; } EnableWindow(g_hBtnPlay, TRUE); } int ConvertRate(WaveIO *pwioDst, const WaveIO *pwioSrc, HWND hWnd) { short *psDataDst; char acBuf[16]; int iRate; // サンプリングレートの取得 if (GetWindowText(hWnd, acBuf, sizeof(acBuf)) == 0) { return -1; } if (sscanf_s(acBuf, "%d", &iRate) != 1) { return -2; } if (iRate <= 0) { return -3; } // 変換先データ psDataDst = malloc(pwioSrc->dwSampleLength); if (psDataDst == NULL) { return -4; } memcpy(psDataDst, pwioSrc->psWaveformData, pwioSrc->dwSampleLength); pwioDst->wBitsPerSample = pwioSrc->wBitsPerSample; pwioDst->wChannels = pwioSrc->wChannels; pwioDst->dwSamplesPerSec = iRate; pwioDst->dwSampleLength = pwioSrc->dwSampleLength; pwioDst->psWaveformData = psDataDst; return 0; } int ConvertDec(WaveIO *pwioDst, const WaveIO *pwioSrc, int iDiv) { short *psDataSrc; // 変換元データ short *psDataDst; int iWavLen; // 波長 int *piWavLen; // 波長配列 int iSrcLen; // 変換元データ長 int iDstMax; // 変換先データ長 int iOffsetSrc; int iOffsetDst; int iOffSrc0; int iOffSrc1; int iIndex; int i; // 波長配列の取得 piWavLen = GetWavLen(pwioSrc); if (piWavLen == NULL) { return -1; } // 変換元データ iSrcLen = pwioSrc->dwSampleLength / sizeof(short); psDataSrc = pwioSrc->psWaveformData; // 変換先データ iDstMax = iSrcLen; psDataDst = malloc(iDstMax * sizeof(short)); if (psDataDst == NULL) { return -2; } // 波形データの合成 iOffsetSrc = 0; iOffsetDst = 0; for (iIndex = 0; piWavLen[iIndex]; iIndex++) { iWavLen = piWavLen[iIndex]; iOffSrc0 = iOffsetSrc; iOffSrc1 = iOffsetSrc + iWavLen; if (iIndex % iDiv <= 0) { // 区間(0)←波形データ(0)+波形データ(1) for (i = 0; i < iWavLen; i++) { psDataDst[iOffsetDst + i] = psDataSrc[iOffSrc0 + i] * (iWavLen - i) / (iWavLen + 1) + psDataSrc[iOffSrc1 + i] * (i + 1) / (iWavLen + 1); } iOffsetDst += iWavLen; } else { // 区間(0)←波形データ(0) // 区間(1)←波形データ(1) memcpy(psDataDst + iOffsetDst, psDataSrc + iOffSrc0, iWavLen * 2 * sizeof(short)); iOffsetDst += iWavLen * 2; } // オフセット加算 iOffsetSrc += iWavLen * 2; } free(piWavLen); pwioDst->wBitsPerSample = pwioSrc->wBitsPerSample; pwioDst->wChannels = pwioSrc->wChannels; pwioDst->dwSamplesPerSec = pwioSrc->dwSamplesPerSec; pwioDst->dwSampleLength = iOffsetDst * sizeof(short); pwioDst->psWaveformData = psDataDst; return 0; } int Convert150(WaveIO *pwioDst, const WaveIO *pwioSrc) { short *psDataSrc; // 変換元データ short *psDataDst; int iWavLen; // 波長 int *piWavLen; // 波長配列 int iSrcLen; // 変換元データ長 int iDstMax; // 変換先データ長 int iOffsetSrc; int iOffsetDst; int iOffSrc0; int iOffSrc1; int iOffDst; int iIndex; int i; // 波長配列の取得 piWavLen = GetWavLen(pwioSrc); if (piWavLen == NULL) { return -1; } // 変換元データ iSrcLen = pwioSrc->dwSampleLength / sizeof(short); psDataSrc = pwioSrc->psWaveformData; // 変換先データ iDstMax = (iSrcLen * 3 + 1) / 2; psDataDst = malloc(iDstMax * sizeof(short)); if (psDataDst == NULL) { return -2; } // 波形データの合成 iOffsetSrc = 0; iOffsetDst = 0; for (iIndex = 0; piWavLen[iIndex]; iIndex++) { iWavLen = piWavLen[iIndex]; iOffSrc0 = iOffsetSrc; iOffSrc1 = iOffsetSrc + iWavLen; // 区間(0)←波形データ(0) iOffDst = iOffsetDst; memcpy(psDataDst + iOffDst, psDataSrc + iOffSrc0, iWavLen * sizeof(short)); // 区間(1)←波形データ(0)後+波形データ(1)前 iOffDst = iOffsetDst + iWavLen; for (i = 0; i < iWavLen; i++) { psDataDst[iOffDst + i] = psDataSrc[iOffSrc0 + i] * (i + 1) / (iWavLen + 1) + psDataSrc[iOffSrc1 + i] * (iWavLen - i) / (iWavLen + 1); } // 区間(2)←波形データ(1) iOffDst = iOffsetDst + iWavLen * 2; memcpy(psDataDst + iOffDst, psDataSrc + iOffSrc1, iWavLen * sizeof(short)); // オフセット加算 iOffsetSrc += iWavLen * 2; iOffsetDst += iWavLen * 3; } free(piWavLen); pwioDst->wBitsPerSample = pwioSrc->wBitsPerSample; pwioDst->wChannels = pwioSrc->wChannels; pwioDst->dwSamplesPerSec = pwioSrc->dwSamplesPerSec; pwioDst->dwSampleLength = iOffsetDst * sizeof(short); pwioDst->psWaveformData = psDataDst; return 0; } int Convert200(WaveIO *pwioDst, const WaveIO *pwioSrc) { short *psDataSrc; // 変換元データ short *psDataDst; int iWavLen; // 波長 int *piWavLen; // 波長配列 int iSrcLen; // 変換元データ長 int iDstMax; // 変換先データ長 int iOffsetSrc; int iOffsetDst; int iOffSrc0; int iOffSrc1; int iOffDst; int iLen; int iIndex; int i; // 波長配列の取得 piWavLen = GetWavLen(pwioSrc); if (piWavLen == NULL) { return -1; } // 変換元データ iSrcLen = pwioSrc->dwSampleLength / sizeof(short); psDataSrc = pwioSrc->psWaveformData; // 変換先データ iDstMax = iSrcLen * 2; psDataDst = malloc(iDstMax * sizeof(short)); if (psDataDst == NULL) { return -2; } // 波形データの合成 iOffsetSrc = 0; iOffsetDst = 0; for (iIndex = 0; piWavLen[iIndex]; iIndex++) { iWavLen = piWavLen[iIndex]; iOffSrc0 = iOffsetSrc; iOffSrc1 = iOffsetSrc + iWavLen; // 区間(−1)←波形データ(0)前 if (0 < iIndex) { iOffDst = iOffsetDst - piWavLen[iIndex - 1]; iLen = (piWavLen[iIndex - 1] < iWavLen) ? piWavLen[iIndex - 1] : iWavLen; for (i = 0; i < iLen; i++) { psDataDst[iOffDst + i] += psDataSrc[iOffSrc0 + i] * (iLen - i) / (iLen + 1); } } // 区間(0)←波形データ(0) iOffDst = iOffsetDst; memcpy(psDataDst + iOffDst, psDataSrc + iOffSrc0, iWavLen * sizeof(short)); // 区間(1)←波形データ(0)後+波形データ(1)前 iOffDst = iOffsetDst + iWavLen; for (i = 0; i < iWavLen; i++) { psDataDst[iOffDst + i] = psDataSrc[iOffSrc0 + i] * (i + 1) / (iWavLen + 1) + psDataSrc[iOffSrc1 + i] * (iWavLen - i) / (iWavLen + 1); } // 区間(2)←波形データ(1) iOffDst = iOffsetDst + iWavLen * 2; memcpy(psDataDst + iOffDst, psDataSrc + iOffSrc1, iWavLen * sizeof(short)); // 区間(3)←波形データ(1)後 if (piWavLen[iIndex + 1]) { iOffDst = iOffsetDst + iWavLen * 3; for (i = 0; i < iWavLen; i++) { psDataDst[iOffDst + i] = psDataSrc[iOffSrc1 + i] * (i + 1) / (iWavLen + 1); } } // オフセット加算 iOffsetSrc += iWavLen * 2; iOffsetDst += iWavLen * 4; } free(piWavLen); pwioDst->wBitsPerSample = pwioSrc->wBitsPerSample; pwioDst->wChannels = pwioSrc->wChannels; pwioDst->dwSamplesPerSec = pwioSrc->dwSamplesPerSec; pwioDst->dwSampleLength = (iOffsetDst - iWavLen) * sizeof(short); pwioDst->psWaveformData = psDataDst; return 0; } int* GetWavLen(const WaveIO *pwioSrc) { short *psDataSrc; // 変換元データ int *piWavLen; // 波長配列 int iSrcLen; // 変換元データ長 int iWavLenMin; // 最小波長 int iWavLenMax; // 最大波長 int iWavLen; // 波長 int iWavLenNum; // 波長数 int iOffsetSrc; int iLen; int i; double dTop; double dSum; // 変換元データ iSrcLen = pwioSrc->dwSampleLength / sizeof(short); psDataSrc = pwioSrc->psWaveformData; // 波長 iWavLenMin = pwioSrc->dwSamplesPerSec / 320; // 8KHzの場合320Hz->25 iWavLenMax = pwioSrc->dwSamplesPerSec / 80; // 8KHzの場合80Hz->100 if (iSrcLen < iWavLenMax * 2) { return NULL; } iWavLenNum = 2 + (iSrcLen - iWavLenMax * 2) / iWavLenMin; piWavLen = malloc(iWavLenNum * sizeof(int)); if (piWavLen == NULL) { return NULL; } // 自己相関により波長を求める iWavLenNum = 0; iOffsetSrc = 0; while (iOffsetSrc + iWavLenMax * 2 <= iSrcLen) { iWavLen = 0; for (iLen = iWavLenMin; iLen <= iWavLenMax; iLen++) { dSum = 0.0; for (i = 0; i < iLen; i++) { dSum += psDataSrc[iOffsetSrc + i] * psDataSrc[iOffsetSrc + iLen + i]; } dSum = dSum / iLen; if (iWavLen == 0 || dTop < dSum) { iWavLen = iLen; dTop = dSum; } } // printf("%.3lf %d %d %.1lf\n", // (double)iOffsetSrc / pwioSrc->dwSamplesPerSec, iOffsetSrc, iWavLen, dTop); piWavLen[iWavLenNum++] = iWavLen; iOffsetSrc += iWavLen * 2; } piWavLen[iWavLenNum] = 0; // 波長=0(終端) return piWavLen; } void SetFileInfo(HWND hWnd) { char acFname[_MAX_FNAME]; char acExt[_MAX_EXT]; char acBuf[512]; // タイトルバー if (g_acFile[0]) { _splitpath_s(g_acFile, NULL, 0, NULL, 0, acFname, _MAX_FNAME, acExt, _MAX_EXT); strcpy_s(acBuf, sizeof(acBuf), acFname); strcat_s(acBuf, sizeof(acBuf), acExt); } else { strcpy_s(acBuf, sizeof(acBuf), "無題"); } strcat_s(acBuf, sizeof(acBuf), " - WavePlayer"); SetWindowText(hWnd, acBuf); // ファイルパス SetWindowText(GetDlgItem(hWnd, IDC_EDT_FILE), g_acFile); // ファイル情報 acBuf[0] = '\0'; if (g_acFile[0]) { sprintf_s(acBuf, sizeof(acBuf), "%ubits %uchannels", g_wioSrc.wBitsPerSample, g_wioSrc.wChannels); } SetWindowText(GetDlgItem(hWnd, IDC_EDT_FILEINFO), acBuf); // ビットレート acBuf[0] = '\0'; if (g_acFile[0]) { sprintf_s(acBuf, sizeof(acBuf), "%u", g_wioSrc.dwSamplesPerSec); } SetWindowText(GetDlgItem(hWnd, IDC_EDT_SRCRATE), acBuf); }
resource.h
#define IDC_STATIC (-1) #define IDD_WAVEPLAYER 100 #define IDC_EDT_FILE 1000 #define IDC_EDT_VOLUME 1001 #define IDC_EDT_SRCRATE 1002 #define IDC_EDT_FILEINFO 1003 #define IDC_EDT_DSTRATE 1004 #define IDC_RAD_1 1011 #define IDC_RAD_2 1012 #define IDC_RAD_3 1013 #define IDC_RAD_4 1014 #define IDC_RAD_5 1015 #define IDC_RAD_6 1016 #define IDC_RAD_7 1017 #define IDC_RAD_8 1018 #define IDC_RAD_9 1019 #define IDC_RAD_10 1020 #define IDC_BTN_STOP 1030 #define IDC_BTN_PLAY 1031
WavePlayer.rc
// リソーススクリプト #include
#include "resource.h" IDD_WAVEPLAYER DIALOGEX 0, 0, 240, 180 STYLE WS_POPUPWINDOW | WS_MINIMIZEBOX EXSTYLE WS_EX_APPWINDOW | WS_EX_ACCEPTFILES CAPTION "WavePlayer" // FONT 9, "MS Pゴシック" BEGIN EDITTEXT IDC_EDT_FILE,4,4,232,36, ES_MULTILINE | ES_AUTOVSCROLL | ES_WANTRETURN LTEXT "音量:",IDC_STATIC,8,48,32,8 EDITTEXT IDC_EDT_VOLUME,44,48,20,12,WS_DISABLED LTEXT "%",IDC_STATIC,68,48,8,8 LTEXT "通常:",IDC_STATIC,8,64,32,8 EDITTEXT IDC_EDT_SRCRATE,60,64,32,12,WS_DISABLED LTEXT "Hz",IDC_STATIC,96,64,12,8 EDITTEXT IDC_EDT_FILEINFO,112,64,96,12 LTEXT "レート:",IDC_STATIC,8,80,32,8 EDITTEXT IDC_EDT_DSTRATE,60,80,32,12 LTEXT "Hz",IDC_STATIC,96,80,12,8 LTEXT "音程:",IDC_STATIC,8,96,32,8 LTEXT "時間:",IDC_STATIC,8,128,32,8 CONTROL "",IDC_RAD_1,"Button",BS_AUTORADIOBUTTON | WS_GROUP, 44,64,8,8 CONTROL "",IDC_RAD_2,"Button",BS_AUTORADIOBUTTON, 44,80,8,8 CONTROL "150%",IDC_RAD_3,"Button",BS_AUTORADIOBUTTON, 44,96,32,8 CONTROL "200%",IDC_RAD_4,"Button",BS_AUTORADIOBUTTON, 80,96,32,8 CONTROL "75%",IDC_RAD_5,"Button",BS_AUTORADIOBUTTON, 44,112,32,8 CONTROL "50%",IDC_RAD_6,"Button",BS_AUTORADIOBUTTON, 80,112,32,8 CONTROL "150%",IDC_RAD_7,"Button",BS_AUTORADIOBUTTON, 44,128,32,8 CONTROL "200%",IDC_RAD_8,"Button",BS_AUTORADIOBUTTON, 80,128,32,8 CONTROL "75%",IDC_RAD_9,"Button",BS_AUTORADIOBUTTON, 44,144,32,8 CONTROL "50%",IDC_RAD_10,"Button",BS_AUTORADIOBUTTON, 80,144,32,8 PUSHBUTTON "■",IDC_BTN_STOP,4,164,32,12,WS_GROUP PUSHBUTTON "▲",IDC_BTN_PLAY,40,164,32,12 END