Skip to content

Instantly share code, notes, and snippets.

@hirosof
Created December 18, 2012 14:30
Show Gist options
  • Select an option

  • Save hirosof/4328451 to your computer and use it in GitHub Desktop.

Select an option

Save hirosof/4328451 to your computer and use it in GitHub Desktop.
/*----------------------------------------------------------------------------
プログラム名:HSWavePlayerPrototype
バージョン:1.0.10.0
プログラム概要:
開発言語:Microsoft Visual C++ 2012
統合開発環境:Microsoft Visual Studio 2012 Professional Edition
開発開始日:2012/12/09
最終更新日:2012/12/18
-------------------------------------------------------------------------------
更新日一覧
2012/12/09 ・・・ 1.0.1.0
2012/12/10 ・・・ 1.0.2.0
2012/12/11 ・・・ 1.0.3.0
2012/12/12 ・・・ 1.0.4.0
2012/12/13 ・・・ 1.0.5.0
2012/12/14 ・・・ 1.0.6.0
2012/12/15 ・・・ 1.0.7.0
2012/12/16 ・・・ 1.0.8.0
2012/12/17 ・・・ 1.0.9.0
2012/12/18 ・・・ 1.0.10.0
--------------------------------------------------------------------------------*/
/*
ビジュアライザーの色
ステレオ(L) : HSV(30,0.5,1) RGB(255,191,127)
ステレオ(R) : HSV(210,0.5,1) RGB(127,191,255)
モノラル(M) : HSV(90,0.5,1) RGB(191,255,127)
*/
/*-----------------------インクルード部------------------------*/
#include <windows.h>
#include <TCHAR.H >
#include "inc\CHSLine\CHSLine.h"
#include "inc\HSCOLOR\HSCOLOR.h"
#include "inc\HSFFT\HSFFT.h"
#include "inc\wave\WaveFunc.h"
#include "inc\myfuncs.h"
#include "inc\HSCommCtrl.h"
#include "resource.h"
#include "HSTrackBar.h"
/*-------------------------------------------------------------*/
/*-------------------プロトタイプ宣言部------------------------*/
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
ATOM SetApp(HINSTANCE);
HWND SetInstance(HINSTANCE,int);
void GetPositionTimeString(TCHAR * ,unsigned int ,unsigned int);
void GetPositionTimeStringEx(TCHAR * ,unsigned int ,unsigned int);
int DeviceListAddToMainMenu(HWND , int *DevItemMaxID = NULL , int SelectDeviceID = WAVE_MAPPER);
void SetStatusBarTextForVolumeAndSpeed(HWND , double , int);
void DrawProgressPositionTimeWithSimpleMeter(HDC ,int,int , unsigned int, unsigned int , LPWaveFileBaseHeader , double * , int);
void __stdcall mmTimerCallBack(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2);
void ConvNormalizeFromData(double *out , WAVEDN *lpOld , WAVEDN *lpPlay1 , WAVEDN *lpPlay2 , WaveFileInfo wfi);
void EasyVocalEraser(WAVEDN* , WaveFileInfo);
//ビジュアライザーの型
typedef void (*pHSWavePlayerVisualizer)(HDC , int , int , LPWaveFileBaseHeader , double * , int);
void WPV_DrawWave(HDC , int , int , LPWaveFileBaseHeader , double * , int);
void WPV_DrawWaveABS(HDC , int , int , LPWaveFileBaseHeader , double * , int);
void WPV_DrawPeekMeter(HDC , int , int , LPWaveFileBaseHeader , double * , int);
void WPV_DrawVUMeter(HDC , int , int , LPWaveFileBaseHeader , double * , int);
void WPV_DrawVUMeter2(HDC , int , int , LPWaveFileBaseHeader , double * , int);
void WPV_SpectrumWave(HDC , int , int , LPWaveFileBaseHeader , double * , int);
void WPV_SpectrumWave2(HDC , int , int , LPWaveFileBaseHeader , double * , int);
void WPV_SpectrumWave3(HDC , int , int , LPWaveFileBaseHeader , double * , int);
void WPV_SpectrumBar(HDC , int , int , LPWaveFileBaseHeader , double * , int);
void WPV_SpectrumBar2(HDC , int , int , LPWaveFileBaseHeader , double * , int);
void WPV_SpectrumMeter(HDC , int , int , LPWaveFileBaseHeader , double * , int);
void WPV_SpectrumMeter2(HDC , int , int , LPWaveFileBaseHeader , double * , int);
//マニフェスト登録
#pragma comment(linker,"\"/manifestdependency:type='win32' " \
"name='Microsoft.Windows.Common-Controls' " \
"version='6.0.0.0' " \
"processorArchitecture='X86' " \
"publicKeyToken='6595b64144ccf1df' " \
"language='*'\"")
/*-------------------------------------------------------------*/
/*-------------------------マクロ定義部------------------------*/
#define PRONAME "HSWavePlayerPrototype"
#define PROVER "1.0.10.0"
#define PRONAME_TXT TEXT(PRONAME)
#define PROVER_TXT TEXT(PROVER)
#define WindowClientSizeX 640
#define WindowClientSizeY 360
#define DEVICERESCANID 2000
#define DEVICESELECTSTARTID 20000
#define REDRAW_TIMEMINLATE 1000 //最も遅い
#define REDRAW_TIMEQUITELATE 500 //かなり遅い(Lv2)
#define REDRAW_TIMEVERYLATE 100 //かなり遅い(Lv1)
#define REDRAW_TIMELATE 75 //遅い
#define REDRAW_TIMELOWLATE 62 //少し遅い
#define REDRAW_TIMENORMAL 50 //普通
#define REDRAW_TIMELOWFAST 37 //少し早い
#define REDRAW_TIMEFAST 25 //早い
#define REDRAW_TIMEVERYFAST 10 //とても速い(Lv1)
#define REDRAW_TIMEQUITEFAST 5 //とても速い(Lv2)
#define REDRAW_TIMEMAXFAST 1 //最も早い
enum MyMessage
{
TIMER_REDRAW = (WM_APP + 100),
WAVE_OPEN ,
WAVE_PLAYPAUSE,
WAVE_STOP,
WAVE_SEEK10,
WAVE_SPEED005
};
/*-------------------------------------------------------------*/
/*-------------------グローバル変数定義部----------------------*/
//#define ProgressTimeStringMiliseconds 1
bool ProgressTimeStringMiliseconds = true;
TCHAR szClassName[] = PRONAME_TXT; //ウィンドウクラス
const int MaxDecibel = 60;
/*-------------------------------------------------------------*/
/*----------------------------メイン関数定義部--------------------------------------------*/
int WINAPI WinMain(HINSTANCE hCurInst,HINSTANCE hPrevInst, LPSTR lpsCmdLine,int nCmdShow){
MSG msg;
BOOL bRet;
HWND hParent;
if (!SetApp(hCurInst)) return FALSE;
if (!(hParent = SetInstance(hCurInst,nCmdShow))) return FALSE;
HACCEL hAccel = LoadAccelerators(hCurInst , MAKEINTRESOURCE(IDR_MAINACCELERATOR));
while ((bRet=GetMessage(&msg,NULL,0,0))){
if(bRet==-1){
MessageBox(NULL,TEXT("GetMessageエラー"),TEXT("Error"),MB_OK);
break;
}else{
if(!TranslateAccelerator(hParent , hAccel , &msg)){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
return (int)msg.wParam;
}
/*---------------------------------------------------------------------------------------*/
/*------------------------ウィンドウクラスを登録する関数の定義部-------------------------*/
ATOM SetApp(HINSTANCE hInst){
WNDCLASSEX wc; //WNDCLASSEX構造体
wc.cbSize=sizeof(WNDCLASSEX);
wc.style=CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
wc.lpfnWndProc=WndProc; //プロシージャ名
wc.cbClsExtra=0;
wc.cbWndExtra=0;
wc.hInstance=hInst ; //インスタンス
wc.hIcon=(HICON)LoadImage(NULL,MAKEINTRESOURCE(IDI_APPLICATION),IMAGE_ICON,0,0,LR_DEFAULTSIZE | LR_SHARED);
wc.hCursor=(HCURSOR)LoadImage(NULL,MAKEINTRESOURCE(IDC_ARROW),IMAGE_CURSOR,0,0,LR_DEFAULTSIZE | LR_SHARED);
wc.hbrBackground=CreateSolidBrush(RGB(240,240,240));
wc.lpszMenuName=MAKEINTRESOURCE(IDR_MAINMENU); //メニュー名
wc.lpszClassName=szClassName;
wc.hIconSm=(HICON)LoadImage(NULL,MAKEINTRESOURCE(IDI_APPLICATION),IMAGE_ICON,0,0,LR_DEFAULTSIZE | LR_SHARED);
return (RegisterClassEx(&wc));
}
/*---------------------------------------------------------------------------------------*/
/*-----------------------ウィンドウを作成する関数の定義部--------------------------------*/
HWND SetInstance(HINSTANCE hInst,int nCmdShow){
HWND hwnd;
hwnd =
CreateWindowEx(NULL,
szClassName,
//タイトルバーにこの文字列が表示されます
PRONAME_TXT,
WS_OVERLAPPEDWINDOW,//ウィンドウの種類
CW_USEDEFAULT, //x座標
CW_USEDEFAULT,//y座標
CW_USEDEFAULT, //幅
CW_USEDEFAULT,//高さ
NULL,//親ウィンドウのハンドル、親を作るときはNULL
NULL,//メニューハンドル、クラスメニューを使うときはNULL
hInst,//インスタンスハンドル
NULL);
if(!hwnd)return NULL;
//ウィンドウサイズの設定のためのブロック
{
RECT Window,Client;
POINT ptW,ptC;
GetWindowRect(hwnd,&Window);
GetClientRect(hwnd,&Client);
ptW.x = Window.right - Window.left;
ptW.y = Window.bottom - Window.top;
ptC.x = Client.right - Client.left;
ptC.y = Client.bottom - Client.top;
SetWindowPos(hwnd,NULL,0,0,WindowClientSizeX+(ptW.x - ptC.x),WindowClientSizeY+(ptW.y - ptC.y),SWP_NOZORDER | SWP_NOMOVE);
}
ShowWindow(hwnd,nCmdShow);
UpdateWindow(hwnd);
return hwnd;
}
/*-------------------------------------------------------------------------------------*/
/*------------------メインウィンドウのウィンドウプロシージャの定義部---------------------*/
//タイマー
MMRESULT TimerID = 0;
HWND hParent;
LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WPARAM wp,LPARAM lp){
//ボタン
static HWND hButton[2];
static TCHAR ButtonText[3][10] = {TEXT("再生") , TEXT("一時停止") , TEXT("停止")};
//トラックバー
static HWND hTrack;
//ステータスバー
static HWND hStatus;
static int StatusBarSizeY = 0;
static int SB_CenterTextSize = 0 ;
//オブジェクトフォント
static HFONT hFont_Button = NULL , hFont_Status = NULL;
//背景色ブラシ
static HBRUSH hBackBrush;
//デバイスID
static int SelectDeviceID = WAVE_MAPPER , SDID_MENUMAX = 0;
//ファイル入力関連
static TCHAR lpszPlayFile[MAX_PATH] = {0} , lpszNextPlayFile[MAX_PATH] = {0};
static HANDLE hPlayFile = 0 , hNextPlayFile = 0;
//再生関連
static WAVEDN *lpData[2] = {0,0}, *lpOldData = 0;
static double *lpFloatDataForVisualizer = 0;
static WAVEHDR wh[2];
//ファイル情報
static WaveFileInfo wfi;
static LPWaveFileBaseHeader lpWFBH = &wfi.tagWaveFileBaseHeader;
static int PlayTimeMS = 0 , PlayPositonMS = 0 , isPause = 0 , PlayPositonSamples = 0;
static int isQuitAddData = 0 , QuitAddDataID = 0 , BufID = 0;
static int PlayTimePositonPadding = 0 , PlayPositonSamplesPadding = 0 , PlayPosFromSmprate = 0;
static __int64 AfterInputDataSamples = 0;
static int PlayFileSamplingRate = 0;
//waveOut系関数使用
static HWAVEOUT hwo = NULL;
static int OnSeeking = 0;
static int SeekToSamples = 0;
static int PlayVolume = 0xFFFF;
static double PlaySpeed = 1;
//ビジュアライザ関数
static pHSWavePlayerVisualizer lpVisualizer = WPV_DrawWave;
//その他
static BOOL bRepeat = FALSE;
static BOOL PlayStopFlag = FALSE;
static BOOL TimerRedraw = FALSE;
static int RedrawTime = REDRAW_TIMENORMAL;
static bool isOnEasyVocalErase = false;
//static bool OnSeekSetKey = false;
//static bool OnSpeedSetKey = false;
//クライアント領域
RECT rt;
GetClientRect(hwnd , &rt);
rt.bottom-=StatusBarSizeY;
switch(msg){
case WM_CREATE:
hParent = hwnd;
hStatus = CreateHSSB(hwnd , NULL);
hFont_Status = MyFont(TEXT("メイリオ") ,20,0,0);
SendMessage(hStatus , WM_SETFONT , (WPARAM)hFont_Status , 1);
{
RECT rt_status;
int x;
SIZE ts_txt;
HDC hdc_status;
int Parts[3];
GetWindowRect(hStatus , &rt_status);
StatusBarSizeY = rt_status.bottom - rt_status.top + 1;
rt.bottom-=StatusBarSizeY;
x = (rt_status.right - rt_status.left + 1);
hdc_status = GetDC(hStatus);
GetTextExtentPoint32(hdc_status , TEXT("速度:x1.00 音量:100%") , lstrlen( TEXT("速度:x1.00 音量:100%")) , &ts_txt);
ReleaseDC(hStatus , hdc_status);
SB_CenterTextSize = ts_txt.cx;
x -= ts_txt.cx;
x/=6;
Parts[0] = x;
Parts[1] = x + SB_CenterTextSize;
Parts[2] = -1;
SetHSSB_SEL(hStatus , 3 , Parts);
SetHSSB_SELTEXT(hStatus , 1 , TEXT("速度:x1.00 音量:100%"));
SetHSSB_SELTEXT(hStatus , 2 , TEXT("ビジュアライザ-:ウェーブ"));
}
hButton[0] = MkButton(hwnd , ButtonText[0] , 5 , rt.bottom - 5 - 68 , 132 , 68 , ID_PLAYPAUSE);
hButton[1] = MkButton(hwnd , ButtonText[2] , 137 , rt.bottom - 5 - 68 , 68 , 68 , ID_STOP);
hFont_Button = MyFont(TEXT("メイリオ") ,40,0,0);
SendMessage(hButton[0] , WM_SETFONT , (WPARAM)hFont_Button , 1);
SendMessage(hButton[1] , WM_SETFONT , (WPARAM)hFont_Button , 1);
hTrack = MkTrackBar(hwnd ,205 ,rt.bottom - 5 - 30,rt.right - 210,25);
TrackBar_SetRange(hTrack , 0 , 1000);
hBackBrush = (HBRUSH)GetClassLong(hwnd,GCL_HBRBACKGROUND);
TimerID = timeSetEvent(1,1,mmTimerCallBack , (DWORD_PTR)hwnd , TIME_ONESHOT);
SelectDeviceID = DeviceListAddToMainMenu(hwnd,&SDID_MENUMAX);
memset(&wfi , 0 , sizeof(wfi));
CheckMenuRadioItem(GetSubMenu(GetMenu(hwnd) , 3) , ID_REDRAW_TIMEMINLATE , ID_REDRAW_TIMEMAXFAST , ID_REDRAW_TIMENORMAL , MF_BYCOMMAND);
break;
case WM_GETMINMAXINFO:
((MINMAXINFO*)lp)->ptMinTrackSize.x = 640;
((MINMAXINFO*)lp)->ptMinTrackSize.y = 300;
break;
case WM_LBUTTONDOWN:
SetFocus(hwnd);
break;
case WM_RBUTTONUP:
{
POINT pt;
bool okChange = true;
pt.x = LOWORD(lp);
pt.y = HIWORD(lp);
okChange &= (pt.x >= 205);
okChange &= (pt.x <= rt.right - 5);
okChange &= (pt.y >= rt.bottom - 5 - 68);
okChange &= (pt.y <= rt.bottom - 5 - 28);
if(okChange)ProgressTimeStringMiliseconds = !ProgressTimeStringMiliseconds;
}
break;
case WM_KEYDOWN:
if(GetKeyState(VK_CONTROL) & 0x80){
if(wp == VK_RIGHT){
if(GetKeyState(VK_SHIFT) & 0x80){
PostMessage(hwnd , WAVE_SPEED005 , 0 , 0);
}else{
PostMessage(hwnd , WAVE_SEEK10 , 0 , 0);
}
}else if(wp == VK_LEFT){
if(GetKeyState(VK_SHIFT) & 0x80){
PostMessage(hwnd , WAVE_SPEED005 , 1 , 0);
}else{
PostMessage(hwnd , WAVE_SEEK10 , 1 , 0);
}
}
}
break;
case WAVE_SEEK10:
if(hwo){
int NowSample = PlayPositonSamples;
int PlusSmpRate = wfi.tagWaveFileBaseHeader.Fmt.tagPCMWaveFormat.wf.nSamplesPerSec * 10;
if(wp == 0){
if((unsigned)(NowSample + PlusSmpRate) <= wfi.FileInfomation.uSamples)
SeekToSamples = NowSample + PlusSmpRate;
PostMessage(hwnd , WAVE_STOP , 2 , 0);
}else{
if(NowSample - PlusSmpRate < 0) SeekToSamples = 0;
else SeekToSamples = NowSample - PlusSmpRate;
PostMessage(hwnd , WAVE_STOP , 2 , 0);
}
}
break;
case WAVE_SPEED005:
PlaySpeed += (wp) ? -0.05 : 0.05;
PlaySpeed = min(4 , max( PlaySpeed , 0.5));
SetStatusBarTextForVolumeAndSpeed(hStatus , PlaySpeed , PlayVolume);
if(hwo){
SeekToSamples = PlayPositonSamples;
PostMessage(hwnd , WAVE_STOP , 2 , 0);
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd , &ps);
//WPV_DrawWave
HDC hdc_mem_visualizer = CreateCompatibleDC(hdc);
HBITMAP hBit_mem_visualizer = CreateCompatibleBitmap(hdc , rt.right - 10 , rt.bottom - 68 - 15);
SelectObject(hdc_mem_visualizer , hBit_mem_visualizer);
PatBlt(hdc_mem_visualizer , 0 , 0 ,rt.right - 10 , rt.bottom - 68 - 15 , BLACKNESS);
if(!hwo)lpVisualizer(hdc_mem_visualizer , rt.right - 10 , rt.bottom - 68 - 15 , NULL , NULL , NULL);
else lpVisualizer(hdc_mem_visualizer , rt.right - 10 , rt.bottom - 68 - 15 ,&wfi.tagWaveFileBaseHeader , lpFloatDataForVisualizer, PlayPosFromSmprate);
HDC hdc_mem_position_text = CreateCompatibleDC(hdc);
HBITMAP hBit_mem_position_text = CreateCompatibleBitmap(hdc , rt.right - 210 , 40);
SelectObject(hdc_mem_position_text , hBit_mem_position_text);
PatBlt(hdc_mem_position_text , 0 , 0 ,rt.right - 210 , 40 , BLACKNESS);
if(!hwo)DrawProgressPositionTimeWithSimpleMeter(hdc_mem_position_text , rt.right - 210 , 40 , PlayPositonMS , PlayTimeMS , 0 , 0 , 0);
else DrawProgressPositionTimeWithSimpleMeter(hdc_mem_position_text , rt.right - 210 , 40 , PlayPositonMS , PlayTimeMS ,&wfi.tagWaveFileBaseHeader , lpFloatDataForVisualizer, PlayPosFromSmprate);
BitBlt(hdc ,5,5,rt.right - 10 , rt.bottom - 68 - 15 , hdc_mem_visualizer , 0,0,SRCCOPY);
BitBlt(hdc , 205 , rt.bottom - 5 - 68 , rt.right - 210 , 40 , hdc_mem_position_text , 0,0,SRCCOPY);
DeleteDC(hdc_mem_position_text);
DeleteDC(hdc_mem_visualizer);
DeleteObject(hBit_mem_position_text);
DeleteObject(hBit_mem_visualizer);
EndPaint(hwnd , &ps);
if(TimerRedraw){
TimerRedraw = FALSE;
TimerID = timeSetEvent(RedrawTime,1,mmTimerCallBack , (DWORD_PTR)hwnd , TIME_ONESHOT);
}
}
break;
case WM_SIZE:
SendMessage(hStatus , msg , wp , lp);
SetWindowPos(hButton[0] , NULL , 5 , rt.bottom - 5 - 68 , 0 , 0 , SWP_NOSIZE |SWP_NOZORDER);
SetWindowPos(hButton[1] , NULL , 137 , rt.bottom - 5 - 68 , 0 , 0 , SWP_NOSIZE |SWP_NOZORDER);
SetWindowPos(hTrack , NULL ,205 ,rt.bottom - 30,rt.right - 210,25 , SWP_NOZORDER);
{
RECT rt_status;
int x;
int Parts[3];
GetWindowRect(hStatus , &rt_status);
x = (rt_status.right - rt_status.left + 1);
x -= SB_CenterTextSize;
x/=6;
Parts[0] = x;
Parts[1] = x + SB_CenterTextSize;
Parts[2] = -1;
SetHSSB_SEL(hStatus , 3 , Parts);
}
//InvalidateRect(hwnd , NULL , TRUE);
break;
case WM_HSCROLL:
if(hwo && !isPause){
if((HWND)lp == hTrack){
if(LOWORD(wp) == SB_ENDSCROLL){
OnSeeking = 0;
// SeekToSamples = (int)(TrackBar_GetPos(hTrack) / 1000.0 * wfi.FileInfomation.uSamples);
SeekToSamples = PlayPositonSamples;
PostMessage(hwnd , WAVE_STOP , 2 , 0);
}else{
OnSeeking = 1;
SeekToSamples = (int)(TrackBar_GetPos(hTrack) / 1000.0 * wfi.FileInfomation.uSamples);
PostMessage(hwnd , WAVE_STOP , 2 , 0);
}
}
}
break;
case WM_COMMAND:
switch(LOWORD(wp)){
case DEVICERESCANID:
if(MessageBox(hwnd , TEXT("再生デバイスを再検索しますか?") , PRONAME_TXT , MB_YESNO | MB_ICONQUESTION) == IDYES){
SelectDeviceID = DeviceListAddToMainMenu(hwnd , &SDID_MENUMAX , SelectDeviceID);
SeekToSamples = PlayPositonSamples;
PostMessage(hwnd , WAVE_STOP , 2 , 0);
}
break;
case ID_APPQUIT:
PostMessage(hwnd ,WM_CLOSE , 0 , 0);
break;
case ID_OPEN:
PostMessage(hwnd , WAVE_OPEN , 0 , 0);
break;
case ID_PLAYPAUSE:
PostMessage(hwnd , WAVE_PLAYPAUSE , 0 , 0);
break;
case ID_STOP:
PostMessage(hwnd , WAVE_STOP , 0 , 0);
break;
case ID_VOLUP:
PlayVolume += 0x0290;
if(PlayVolume > 0xFFFF) PlayVolume = 0xFFFF;
SetStatusBarTextForVolumeAndSpeed(hStatus , PlaySpeed , PlayVolume);
if(hwo)waveOutSetVolume(hwo , MAKELONG(PlayVolume , PlayVolume));
break;
case ID_VOLDOWN:
PlayVolume -= 0x0290;
if(PlayVolume < 0) PlayVolume = 0;
SetStatusBarTextForVolumeAndSpeed(hStatus , PlaySpeed , PlayVolume);
if(hwo)waveOutSetVolume(hwo , MAKELONG(PlayVolume , PlayVolume));
break;
case ID_REPEAT:
{
HMENU hMenu = GetSubMenu(GetMenu(hwnd) , 1);
MENUITEMINFO mmi;
bRepeat = !bRepeat;
mmi.cbSize = sizeof(mmi);
mmi.fMask = MIIM_STATE;
mmi.fState = (bRepeat) ? MFS_CHECKED : MFS_UNCHECKED;
SetMenuItemInfo(hMenu , ID_REPEAT , FALSE , &mmi);
}
break;
case ID_REDRAW_TIMEMINLATE :
RedrawTime = REDRAW_TIMEMINLATE;
CheckMenuRadioItem(GetSubMenu(GetMenu(hwnd) , 3) , ID_REDRAW_TIMEMINLATE , ID_REDRAW_TIMEMAXFAST , LOWORD(wp) , MF_BYCOMMAND);
break;
case ID_REDRAW_TIMEQUITELATE :
RedrawTime = REDRAW_TIMEQUITELATE;
CheckMenuRadioItem(GetSubMenu(GetMenu(hwnd) , 3) , ID_REDRAW_TIMEMINLATE , ID_REDRAW_TIMEMAXFAST , LOWORD(wp) , MF_BYCOMMAND);
break;
case ID_REDRAW_TIMEVERYLATE :
RedrawTime = REDRAW_TIMEVERYLATE;
CheckMenuRadioItem(GetSubMenu(GetMenu(hwnd) , 3) , ID_REDRAW_TIMEMINLATE , ID_REDRAW_TIMEMAXFAST , LOWORD(wp) , MF_BYCOMMAND);
break;
case ID_REDRAW_TIMELATE :
RedrawTime = REDRAW_TIMELATE;
CheckMenuRadioItem(GetSubMenu(GetMenu(hwnd) , 3) , ID_REDRAW_TIMEMINLATE , ID_REDRAW_TIMEMAXFAST , LOWORD(wp) , MF_BYCOMMAND);
break;
case ID_REDRAW_TIMELOWLATE :
RedrawTime = REDRAW_TIMELOWLATE;
CheckMenuRadioItem(GetSubMenu(GetMenu(hwnd) , 3) , ID_REDRAW_TIMEMINLATE , ID_REDRAW_TIMEMAXFAST , LOWORD(wp) , MF_BYCOMMAND);
break;
case ID_REDRAW_TIMENORMAL :
RedrawTime = REDRAW_TIMENORMAL;
CheckMenuRadioItem(GetSubMenu(GetMenu(hwnd) , 3) , ID_REDRAW_TIMEMINLATE , ID_REDRAW_TIMEMAXFAST , LOWORD(wp) , MF_BYCOMMAND);
break;
case ID_REDRAW_TIMELOWFAST :
RedrawTime = REDRAW_TIMELOWFAST;
CheckMenuRadioItem(GetSubMenu(GetMenu(hwnd) , 3) , ID_REDRAW_TIMEMINLATE , ID_REDRAW_TIMEMAXFAST , LOWORD(wp) , MF_BYCOMMAND);
break;
case ID_REDRAW_TIMEFAST :
RedrawTime = REDRAW_TIMEFAST;
CheckMenuRadioItem(GetSubMenu(GetMenu(hwnd) , 3) , ID_REDRAW_TIMEMINLATE , ID_REDRAW_TIMEMAXFAST , LOWORD(wp) , MF_BYCOMMAND);
break;
case ID_REDRAW_TIMEVERYFAST :
RedrawTime = REDRAW_TIMEVERYFAST;
CheckMenuRadioItem(GetSubMenu(GetMenu(hwnd) , 3) , ID_REDRAW_TIMEMINLATE , ID_REDRAW_TIMEMAXFAST , LOWORD(wp) , MF_BYCOMMAND);
break;
case ID_REDRAW_TIMEQUITEFAST :
RedrawTime = REDRAW_TIMEQUITEFAST;
CheckMenuRadioItem(GetSubMenu(GetMenu(hwnd) , 3) , ID_REDRAW_TIMEMINLATE , ID_REDRAW_TIMEMAXFAST , LOWORD(wp) , MF_BYCOMMAND);
break;
case ID_REDRAW_TIMEMAXFAST :
RedrawTime = REDRAW_TIMEMAXFAST;
CheckMenuRadioItem(GetSubMenu(GetMenu(hwnd) , 3) , ID_REDRAW_TIMEMINLATE , ID_REDRAW_TIMEMAXFAST , LOWORD(wp) , MF_BYCOMMAND);
break;
case ID_PLAYSPEED_0_50:
PlaySpeed = 0.50;
SetStatusBarTextForVolumeAndSpeed(hStatus , PlaySpeed , PlayVolume);
if(hwo){
SeekToSamples = PlayPositonSamples;
PostMessage(hwnd , WAVE_STOP , 2 , 0);
}
break;
case ID_PLAYSPEED_0_75:
PlaySpeed = 0.75;
SetStatusBarTextForVolumeAndSpeed(hStatus , PlaySpeed , PlayVolume);
if(hwo){
SeekToSamples = PlayPositonSamples;
PostMessage(hwnd , WAVE_STOP , 2 , 0);
}
break;
case ID_PLAYSPEED_1_00:
PlaySpeed = 1.00;
SetStatusBarTextForVolumeAndSpeed(hStatus , PlaySpeed , PlayVolume);
if(hwo){
SeekToSamples = PlayPositonSamples;
PostMessage(hwnd , WAVE_STOP , 2 , 0);
}
break;
case ID_PLAYSPEED_1_25:
PlaySpeed = 1.25;
SetStatusBarTextForVolumeAndSpeed(hStatus , PlaySpeed , PlayVolume);
if(hwo){
SeekToSamples = PlayPositonSamples;
PostMessage(hwnd , WAVE_STOP , 2 , 0);
}
break;
case ID_PLAYSPEED_1_50:
PlaySpeed = 1.50;
SetStatusBarTextForVolumeAndSpeed(hStatus , PlaySpeed , PlayVolume);
if(hwo){
SeekToSamples = PlayPositonSamples;
PostMessage(hwnd , WAVE_STOP , 2 , 0);
}
break;
case ID_PLAYSPEED_1_75:
PlaySpeed = 1.75;
SetStatusBarTextForVolumeAndSpeed(hStatus , PlaySpeed , PlayVolume);
if(hwo){
SeekToSamples = PlayPositonSamples;
PostMessage(hwnd , WAVE_STOP , 2 , 0);
}
break;
case ID_PLAYSPEED_2_00:
PlaySpeed = 2.00;
SetStatusBarTextForVolumeAndSpeed(hStatus , PlaySpeed , PlayVolume);
if(hwo){
SeekToSamples = PlayPositonSamples;
PostMessage(hwnd , WAVE_STOP , 2 , 0);
}
break;
case ID_SPEED_PLUS:
PostMessage(hwnd , WAVE_SPEED005 , 0 , 0);
break;
case ID_SPEED_MINUS:
PostMessage(hwnd , WAVE_SPEED005 , 1 , 0);
break;
case ID_SEEK_PLUS10SEC:
PostMessage(hwnd , WAVE_SEEK10 , 0 , 0);
case ID_SEEK_MINUS10SEC:
PostMessage(hwnd , WAVE_SEEK10 , 1 , 0);
break;
case ID_EASYVOCALERASE:
isOnEasyVocalErase = !isOnEasyVocalErase;
if(hwo){
SeekToSamples = PlayPositonSamples;
PostMessage(hwnd , WAVE_STOP , 2 , 0);
}
break;
case ID_VR_WAVE:
lpVisualizer = WPV_DrawWave;
SetHSSB_SELTEXT(hStatus , 2 , TEXT("ビジュアライザ-:ウェーブ"));
break;
case ID_VR_ABSWAVE:
lpVisualizer = WPV_DrawWaveABS;
SetHSSB_SELTEXT(hStatus , 2 , TEXT("ビジュアライザ-:絶対値ウェーブ"));
break;
case ID_VR_PEEKMETER:
lpVisualizer = WPV_DrawPeekMeter;
SetHSSB_SELTEXT(hStatus , 2 , TEXT("ビジュアライザ-:ピークメーター"));
break;
case ID_VR_VUMETER:
lpVisualizer = WPV_DrawVUMeter;
SetHSSB_SELTEXT(hStatus , 2 , TEXT("ビジュアライザ-:VUメーター"));
break;
case ID_VR_SPECTRUM_WAVE:
lpVisualizer = WPV_SpectrumWave;
SetHSSB_SELTEXT(hStatus , 2 , TEXT("ビジュアライザ-:スペクトラムウェーブ"));
break;
case ID_VR_SPECTRUM_WAVE2:
lpVisualizer = WPV_SpectrumWave2;
SetHSSB_SELTEXT(hStatus , 2 , TEXT("ビジュアライザ-:スペクトラムウェーブ2"));
break;
case ID_VR_SPECTRUM_WAVE3:
lpVisualizer = WPV_SpectrumWave3;
SetHSSB_SELTEXT(hStatus , 2 , TEXT("ビジュアライザ-:スペクトラムウェーブ3"));
break;
case ID_VR_SPECTRUM_BAR:
lpVisualizer = WPV_SpectrumBar;
SetHSSB_SELTEXT(hStatus , 2 , TEXT("ビジュアライザ-:スペクトラムバー"));
break;
case ID_VR_SPECTRUM_BAR2:
lpVisualizer = WPV_SpectrumBar2;
SetHSSB_SELTEXT(hStatus , 2 , TEXT("ビジュアライザ-:スペクトラムバー2"));
break;
case ID_VR_SPECTRUM_METER:
lpVisualizer = WPV_SpectrumMeter;
SetHSSB_SELTEXT(hStatus , 2 , TEXT("ビジュアライザ-:スペクトラムメーター"));
break;
case ID_VR_SPECTRUM_METER2:
lpVisualizer = WPV_SpectrumMeter2;
SetHSSB_SELTEXT(hStatus , 2 , TEXT("ビジュアライザ-:スペクトラムメーター2"));
break;
case ID_VR_VUMETER2:
lpVisualizer = WPV_DrawVUMeter2;
SetHSSB_SELTEXT(hStatus , 2 , TEXT("ビジュアライザ-:VUメーター2"));
break;
default:
if((LOWORD(wp) >= DEVICESELECTSTARTID) && (LOWORD(wp) <= SDID_MENUMAX)){
SelectDeviceID = LOWORD(wp) - DEVICESELECTSTARTID - 1;
CheckMenuRadioItem(GetSubMenu(GetMenu(hwnd) , 2) , DEVICESELECTSTARTID , SDID_MENUMAX , LOWORD(wp) , MF_BYCOMMAND);
SeekToSamples = PlayPositonSamples;
PostMessage(hwnd , WAVE_STOP , 2 , 0);
}
break;
}
break;
case WAVE_OPEN:
memcpy(lpszNextPlayFile , lpszPlayFile , MAX_PATH * sizeof(TCHAR));
if(WaveFileOpenDialog(hwnd , lpszNextPlayFile , MAX_PATH)){
WaveFileInfo wfi_open;
try{
hNextPlayFile = OpenWaveFile(lpszNextPlayFile , NULL , TRUE);
if(!hNextPlayFile) throw 0;
if(!CheckWaveFile(hNextPlayFile))throw 1;
GetWaveInfo(hNextPlayFile , &wfi_open);
if((wfi_open.tagWaveFileBaseHeader.Fmt.tagPCMWaveFormat.wf.wFormatTag != WAVE_FORMAT_PCM) &&
(wfi_open.tagWaveFileBaseHeader.Fmt.tagPCMWaveFormat.wf.wFormatTag != WAVE_FORMAT_IEEE_FLOAT))throw 2;
}catch(int e){
if(e)CloseWaveFile(hNextPlayFile);
switch(e){
case 0:
MessageBox(hwnd , TEXT("WAVEファイルが開けません") , PRONAME_TXT , MB_ICONERROR);
break;
case 1:
MessageBox(hwnd , TEXT("破損ファイルです") , PRONAME_TXT , MB_ICONERROR);
case 2:
MessageBox(hwnd , TEXT("未対応なフォーマットです") , PRONAME_TXT , MB_ICONERROR);
}
}
PostMessage(hwnd , WAVE_STOP , TRUE , 0);
}
break;
case WAVE_PLAYPAUSE:
if(hwo){
if(isPause) waveOutRestart(hwo);
else waveOutPause(hwo);
isPause = !isPause;
SetWindowText(hButton[0] , ButtonText[!isPause]);
return 0;
}else{
if(hPlayFile == 0){
PostMessage(hwnd , WAVE_OPEN , 0 , 0);
return 0;
}
SetWindowText(hButton[0] , ButtonText[1]);
TCHAR title[512];
wsprintf(title ,TEXT("%s - %s") , PRONAME_TXT , PathFindFileName(lpszPlayFile));
SetWindowText(hwnd , title);
isPause = 0;
GetWaveInfo(hPlayFile , &wfi);
PlayFileSamplingRate = wfi.tagWaveFileBaseHeader.Fmt.tagPCMWaveFormat.wf.nSamplesPerSec;
if(wp == 1){
PlayPositonSamples = PlayPositonSamplesPadding = SeekToSamples;
PlayTimePositonPadding =(int)( (double)SeekToSamples / PlayFileSamplingRate * 1000.0);
}else{
PlayPositonSamplesPadding = 0;
PlayTimePositonPadding = 0;
PlayPositonSamples = 0;
}
PlayPosFromSmprate = 0;
PlayTimeMS = wfi.FileInfomation.uPlayTime;
WAVEFORMATEX wfex;
memcpy(&wfex , &lpWFBH->Fmt.tagPCMWaveFormat , sizeof(PCMWAVEFORMAT));
wfex.cbSize = 0;
wfex.nSamplesPerSec =(int)(wfex.nSamplesPerSec * PlaySpeed);
wfex.nAvgBytesPerSec =(int)(wfex.nAvgBytesPerSec * PlaySpeed);
waveOutOpen(&hwo , SelectDeviceID , &wfex , (DWORD_PTR)hwnd , NULL , CALLBACK_WINDOW);
waveOutSetVolume(hwo , MAKELONG(PlayVolume , PlayVolume));
/*
static WAVEDN *lpData[2] = {0,0}, lpOldData = 0;
static double *lpFloatDataForVisualizer = 0;
*/
lpOldData = (WAVEDN*)HeapAlloc(GetProcessHeap() , HEAP_ZERO_MEMORY , lpWFBH->Fmt.tagPCMWaveFormat.wf.nAvgBytesPerSec);
lpData[0] = (WAVEDN*)HeapAlloc(GetProcessHeap() , HEAP_ZERO_MEMORY , lpWFBH->Fmt.tagPCMWaveFormat.wf.nAvgBytesPerSec);
lpData[1] = (WAVEDN*)HeapAlloc(GetProcessHeap() , HEAP_ZERO_MEMORY , lpWFBH->Fmt.tagPCMWaveFormat.wf.nAvgBytesPerSec);
if(lpWFBH->Fmt.tagPCMWaveFormat.wBitsPerSample == 8){
WAVE8 w8 = 128;
memset(lpOldData , w8 , lpWFBH->Fmt.tagPCMWaveFormat.wf.nAvgBytesPerSec);
memset(lpData[0] , w8 , lpWFBH->Fmt.tagPCMWaveFormat.wf.nAvgBytesPerSec);
memset(lpData[1] , w8 , lpWFBH->Fmt.tagPCMWaveFormat.wf.nAvgBytesPerSec);
}
lpFloatDataForVisualizer = (double*)HeapAlloc(GetProcessHeap() , HEAP_ZERO_MEMORY , PlayFileSamplingRate * lpWFBH->Fmt.tagPCMWaveFormat.wf.nChannels * sizeof(double) * 3);
for (int i = 0; i < 2; i++)
{
memset(&wh[i] , 0 ,sizeof(WAVEHDR));
wh[i].lpData = (LPSTR)lpData[i];
wh[i].dwBufferLength = lpWFBH->Fmt.tagPCMWaveFormat.wf.nAvgBytesPerSec;
wh[i].dwUser = 0;
wh[i].dwFlags = WHDR_BEGINLOOP | WHDR_ENDLOOP;
wh[i].dwLoops = 1;
waveOutPrepareHeader(hwo , &wh[i] , sizeof(WAVEHDR));
}
//static int isQuitAddData = 0 , QuitAddDataID = 0;
isQuitAddData = 0;
QuitAddDataID = 0;
AfterInputDataSamples = 0;
if(wp == 1){
//if(OnSeeking == 0)
{
int Tmp[3];
Tmp[0] = SeekToSamples - PlayFileSamplingRate + 1;
Tmp[1] = PlayFileSamplingRate;
if(Tmp[0] < 0){
Tmp[1] += Tmp[0];
Tmp[2] = -Tmp[0];
Tmp[0] = 0;
}else Tmp[2] = 0;
ReadWaveDataSamples(hPlayFile , lpOldData + Tmp[2] * wfex.nBlockAlign , Tmp[0], Tmp[1] );
if(isOnEasyVocalErase)EasyVocalEraser(lpOldData , wfi);
}
wh[0].dwBufferLength = ReadWaveDataSamples(hPlayFile , lpData[0] , SeekToSamples,PlayFileSamplingRate);
AfterInputDataSamples+=SeekToSamples;
//MessageBox(hwnd , 0 , 0 , 0);
}else{
wh[0].dwBufferLength = ReadWaveDataSeconds(hPlayFile , lpData[0] , 0,1);
}
BufID = 0;
if(isOnEasyVocalErase)EasyVocalEraser(lpData[0] , wfi);
waveOutWrite(hwo , &wh[0] , sizeof(WAVEHDR));
if(wh[0].dwBufferLength == lpWFBH->Fmt.tagPCMWaveFormat.wf.nAvgBytesPerSec){
AfterInputDataSamples += PlayFileSamplingRate;
wh[1].dwBufferLength = ReadWaveDataSamples(hPlayFile , lpData[1] , (int)AfterInputDataSamples,PlayFileSamplingRate);
if(isOnEasyVocalErase)EasyVocalEraser(lpData[1] , wfi);
waveOutWrite(hwo , &wh[1], sizeof(WAVEHDR));
if(wh[1].dwBufferLength == lpWFBH->Fmt.tagPCMWaveFormat.wf.nAvgBytesPerSec){
AfterInputDataSamples += PlayFileSamplingRate;
}else{
isQuitAddData = 1;
QuitAddDataID = 1;
}
BufID = 1;
}else{
isQuitAddData = 1;
QuitAddDataID = 0;
}
ConvNormalizeFromData(lpFloatDataForVisualizer , lpOldData , lpData[0] , lpData[1] , wfi);
}
break;
case WAVE_STOP:
// InvalidateRect(hwnd , NULL ,TRUE);
if(hwo){
if(wp == 1){
wh[0].dwUser = wh[1].dwUser = 101;
}else if(wp == 2){
wh[0].dwUser = wh[1].dwUser = 102;
}else wh[0].dwUser = wh[1].dwUser = 100;
if(wp != 2)SetWindowText(hButton[0] , ButtonText[0]);
waveOutReset(hwo);
}else if(wp == 1){
CloseWaveFile(hPlayFile);
hPlayFile = hNextPlayFile;
memcpy(lpszPlayFile , lpszNextPlayFile , MAX_PATH * sizeof(TCHAR));
PostMessage(hwnd , WAVE_PLAYPAUSE , 0 , 0);
}
break;
case TIMER_REDRAW:
{
RECT rcRedraw;
TimerRedraw = TRUE;
//再生状況表示
if(hwo){
MMTIME mmt;
mmt.wType = TIME_SAMPLES;
waveOutGetPosition(hwo , &mmt , sizeof(mmt));
PlayPositonSamples = PlayPositonSamplesPadding + mmt.u.sample;
PlayPosFromSmprate = mmt.u.sample % wfi.tagWaveFileBaseHeader.Fmt.tagPCMWaveFormat.wf.nSamplesPerSec;
PlayPositonMS = PlayTimePositonPadding;
PlayPositonMS +=(int)( (double)mmt.u.sample / wfi.tagWaveFileBaseHeader.Fmt.tagPCMWaveFormat.wf.nSamplesPerSec * 1000);
if(!OnSeeking){
TrackBar_SetPos(hTrack , (int)((double)PlayPositonSamples / wfi.FileInfomation.uSamples * 1000));
}
}else{
if(PlayStopFlag){
PlayPositonMS = 0;
TrackBar_SetPos(hTrack ,0);
if(TrackBar_GetPos(hTrack) == 0)PlayStopFlag = FALSE;
}
}
rcRedraw.left = 205 ;
rcRedraw.top = rt.bottom - 5 - 68;
rcRedraw.right = rt.right - 5;
rcRedraw.bottom = rcRedraw.top + 40;
InvalidateRect(hwnd , &rcRedraw , FALSE);
rcRedraw = rt;
//rt.bottom - 68 - 15
rcRedraw.bottom -= (68 - 5);
InvalidateRect(hwnd , &rcRedraw , FALSE);
// InvalidateRect(hButton[0] , NULL,FALSE);
// InvalidateRect(hButton[1] , NULL,FALSE);
}
break;
case MM_WOM_DONE:
{
WAVEHDR *lpwh = (WAVEHDR*)lp;
if(lpwh->dwUser >= 100){
waveOutUnprepareHeader(hwo , lpwh , sizeof(WAVEHDR));
HeapFree(GetProcessHeap() , NULL , lpwh->lpData);
lpData[(lpwh->lpData == (LPSTR)lpData[0]) ? 0 : 1] = NULL;
if(lpwh == &wh[BufID]){
HeapFree(GetProcessHeap() , NULL , lpOldData);
HeapFree(GetProcessHeap() , NULL , lpFloatDataForVisualizer);
waveOutClose(hwo);
hwo = 0;
if(lpwh->dwUser != 102)PlayStopFlag = TRUE;
if(lpwh->dwUser >= 101){
if(lpwh->dwUser==101){
// TrackBar_SetPos(hTrack , 0);
CloseWaveFile(hPlayFile);
hPlayFile = hNextPlayFile;
memcpy(lpszPlayFile , lpszNextPlayFile , MAX_PATH * sizeof(TCHAR));
}
PostMessage(hwnd ,WAVE_PLAYPAUSE , lpwh->dwUser-101 , 0);
}
}
return 0;
}
if(isQuitAddData){
waveOutUnprepareHeader(hwo , lpwh , sizeof(WAVEHDR));
HeapFree(GetProcessHeap() , NULL , lpwh->lpData);
lpData[(lpwh->lpData == (LPSTR)lpData[0]) ? 0 : 1] = NULL;
if(lpwh == &wh[QuitAddDataID]){
waveOutClose(hwo);
HeapFree(GetProcessHeap() , NULL , lpOldData);
HeapFree(GetProcessHeap() , NULL , lpFloatDataForVisualizer);
hwo = 0;
PlayStopFlag = TRUE;
// TrackBar_SetPos(hTrack , 0);
if(bRepeat)PostMessage(hwnd ,WAVE_PLAYPAUSE , 0 , 0);
else SetWindowText(hButton[0] , ButtonText[0]);
}
return 0;
}
memcpy(lpOldData , lpwh->lpData , lpwh->dwBufferLength);
if(lpWFBH->Fmt.tagPCMWaveFormat.wBitsPerSample == 8){
memset(lpwh->lpData , 128 , lpwh->dwBufferLength);
}else{
memset(lpwh->lpData , 0 , lpwh->dwBufferLength);
}
lpwh->dwBufferLength = ReadWaveDataSamples(hPlayFile , lpwh->lpData , (unsigned int)AfterInputDataSamples , lpWFBH->Fmt.tagPCMWaveFormat.wf.nSamplesPerSec);
BufID = (lpwh->lpData == (LPSTR)lpData[0]) ? 0 : 1;
if(lpwh->dwBufferLength == 0){
isQuitAddData = 1;
QuitAddDataID = !BufID;
}else{
if(isOnEasyVocalErase)EasyVocalEraser(lpwh->lpData , wfi);
AfterInputDataSamples += lpWFBH->Fmt.tagPCMWaveFormat.wf.nSamplesPerSec;
if(lpwh->lpData == (LPSTR)lpData[0]){
ConvNormalizeFromData(lpFloatDataForVisualizer , lpOldData , lpData[1] , lpData[0] , wfi);
}else{
ConvNormalizeFromData(lpFloatDataForVisualizer , lpOldData , lpData[0] , lpData[1] , wfi);
}
waveOutWrite(hwo , lpwh , sizeof(WAVEHDR));
if(lpwh->dwBufferLength != lpWFBH->Fmt.tagPCMWaveFormat.wf.nAvgBytesPerSec){
isQuitAddData = 1;
QuitAddDataID = (lpwh->lpData == (LPSTR)lpData[0]) ? 0 : 1;
}
}
}
break;
case WM_DESTROY:
DeleteObject(hFont_Button);
DeleteObject(hFont_Status);
DestroyMenu(GetSubMenu(GetMenu(hwnd) , 2));
SendMessage(hwnd , WAVE_STOP , 0 , 0);
timeKillEvent(TimerID);
PostQuitMessage(0);
break;
default:
return (DefWindowProc(hwnd,msg,wp,lp));
}
return 0;
}
void SetStatusBarTextForVolumeAndSpeed(HWND hStatus, double speed, int volume){
TCHAR txt[64];
_stprintf_s(txt , TEXT("速度:x%.2f 音量:%d%%") , speed ,
(int)((double)volume / 0xFFFF * 100));
SetHSSB_SELTEXT(hStatus , 1 , txt);
}
void EasyVocalEraser(WAVEDN *data , WaveFileInfo wfi){
double bL , bR , *lpL , *lpR;
double *NData;
if(wfi.tagWaveFileBaseHeader.Fmt.tagPCMWaveFormat.wf.nChannels == 1) return;
int SmpRate = wfi.tagWaveFileBaseHeader.Fmt.tagPCMWaveFormat.wf.nSamplesPerSec;
NData = (double*)HeapAlloc(GetProcessHeap() , HEAP_ZERO_MEMORY , SmpRate * 2 *sizeof(double));
WaveNormalize(data , wfi.tagWaveFileBaseHeader.Fmt.tagPCMWaveFormat.wf.nAvgBytesPerSec , NData ,
&wfi.tagWaveFileBaseHeader.Fmt.tagPCMWaveFormat);
for (int i = 0; i < SmpRate; i++)
{
lpL = NData + i*2;
lpR = NData + i*2 + 1;
bL = *lpR - *lpL;
bR = *lpL - *lpR;
*lpL = bL;
*lpR = bR;
}
WaveUnNormalize(NData , SmpRate * 2 *sizeof(double) , data ,
&wfi.tagWaveFileBaseHeader.Fmt.tagPCMWaveFormat);
HeapFree(GetProcessHeap() , NULL , NData);
}
void DrawProgressPositionTimeWithSimpleMeter(HDC hdc, int sizex, int sizey ,unsigned int nowtime, unsigned int mediatimes, LPWaveFileBaseHeader lpHeader, double *lpData , int possamples){
HFONT hFont , hOldFont;
TCHAR string[32];
SIZE strSize;
int VUMeterSizeX;
if(!hdc)return;
//hFont = MyFont(TEXT("メイリオ") , 32 , 0 , 0);
hFont = MyFont(TEXT("メイリオ") , 40 , 0 , 0);
hOldFont = (HFONT)SelectObject(hdc , hFont);
SetBkMode(hdc ,TRANSPARENT);
if(ProgressTimeStringMiliseconds)
GetPositionTimeStringEx(string , nowtime , mediatimes);
else
GetPositionTimeString(string , nowtime/1000 , mediatimes/1000);
SetTextColor(hdc , RGB(170,255,165));
GetTextExtentPoint32(hdc , string , lstrlen(string) , &strSize);
TextOut(hdc , (sizex - strSize.cx) / 2 , (sizey - strSize.cy) / 2 ,string , lstrlen(string) );
VUMeterSizeX = (sizex - 20) - strSize.cx;
VUMeterSizeX /= 2;
if(lpHeader && lpData && VUMeterSizeX >= 50){
CHSLine line(hdc);
line.SetColorHSV(120 , 1 , 1);
int Channel = lpHeader->Fmt.tagPCMWaveFormat.wf.nChannels;
int UseSamples =(int)(0.3 * lpHeader->Fmt.tagPCMWaveFormat.wf.nSamplesPerSec);
double Average[2] = {0 , 0};
int start , end;
if(UseSamples%2)UseSamples++;
start = -UseSamples/2;
end = UseSamples/2 - 1;
//start = -UseSamples + 1;
//end = 0;
lpData += lpHeader->Fmt.tagPCMWaveFormat.wf.nSamplesPerSec * Channel;
lpData += (possamples % lpHeader->Fmt.tagPCMWaveFormat.wf.nSamplesPerSec) * Channel;
double data;
for (int pos = start; pos <= end; pos++)
{
if(Channel == 2){
data = *(lpData + pos*2);
if(data >= 0)
Average[0] += data;
else
Average[0] -= data;
data = *(lpData + pos*2+1);
if(data >= 0)
Average[1] += data;
else
Average[1] -= data;
}else{
data = *(lpData + pos);
if(data >= 0)
Average[0] += data;
else
Average[0] -= data;
Average[1] = Average[0];
}
}
Average[0] /= UseSamples;
Average[1] /= UseSamples;
//L
double Decibel;
int size;
if(Average[0]){
Decibel = 20 * log10(Average[0]);
if(Decibel >= -MaxDecibel){
Decibel+=MaxDecibel;
size = (int)((Decibel / MaxDecibel) * VUMeterSizeX);
for (int i = 0; i < size; i++)
{
double h;
h = (double)i / (VUMeterSizeX - 1) * 60;
if(Channel == 2)line.SetColorH(60 - h);
else line.SetColorH(150 - h);
line.DrawEx((sizex - strSize.cx) / 2 - 5 - i , 1 , (sizex - strSize.cx) / 2 - 5 - i, sizey - 2);
}
}
}
//R
if(Average[1]){
Decibel = 20 * log10(Average[1]);
if(Decibel >= -MaxDecibel){
Decibel+=MaxDecibel;
size = (int)((Decibel / MaxDecibel) * VUMeterSizeX);
for (int i = 0; i < size; i++)
{
double h;
h = (double)i / (VUMeterSizeX - 1) * 60;
if(Channel == 2)line.SetColorH(180 + h);
else line.SetColorH(150 - h);
line.DrawEx((sizex - strSize.cx) / 2 + strSize.cx + i + 5 , 1 , (sizex - strSize.cx) / 2 + strSize.cx + i + 5 , sizey - 2);
}
}
}
}
SelectObject(hdc , hOldFont);
DeleteObject(hFont);
}
int DeviceListAddToMainMenu(HWND hwnd, int *DevItemMaxID , int SelectDeviceID){
if(!hwnd) return -2;
HMENU hMenu = GetMenu(hwnd);
HMENU hSubMenu = CreatePopupMenu();
HMENU hOldSubMenu = GetSubMenu(hMenu , 2);
int DevNum = waveOutGetNumDevs();
WAVEOUTCAPS woc;
MENUITEMINFO mmi;
if(SelectDeviceID >= DevNum) SelectDeviceID = WAVE_MAPPER;
if(DevItemMaxID) *DevItemMaxID = DEVICESELECTSTARTID + DevNum;
//デバイス一覧を作成
for (int i = -1; i < DevNum; i++)
{
waveOutGetDevCaps(i , &woc , sizeof(woc));
memset(&mmi , 0 , sizeof(mmi));
mmi.cbSize = sizeof(MENUITEMINFO);
mmi.fMask = MIIM_FTYPE | MIIM_ID | MIIM_STATE | MIIM_STRING;
mmi.fType = MFT_RADIOCHECK | MFT_STRING;
if(i == -1)mmi.fState = MFS_DEFAULT;
if(i == SelectDeviceID) mmi.fState |= MFS_CHECKED;
mmi.wID = DEVICESELECTSTARTID + (i + 1);
mmi.dwTypeData = woc.szPname;
mmi.cch = lstrlen(woc.szPname);
InsertMenuItem(hSubMenu , GetMenuItemCount(hSubMenu) , TRUE , &mmi);
}
//セパレーターを追加
memset(&mmi , 0 , sizeof(mmi));
mmi.cbSize = sizeof(MENUITEMINFO);
mmi.fMask = MIIM_TYPE|MIIM_STATE;
mmi.fType = MFT_SEPARATOR;
mmi.fState = MFS_GRAYED;
InsertMenuItem(hSubMenu , GetMenuItemCount(hSubMenu) , TRUE , &mmi);
//デバイス再検索用のメニューを追加
memset(&mmi , 0 , sizeof(mmi));
mmi.cbSize = sizeof(MENUITEMINFO);
mmi.fMask = MIIM_FTYPE | MIIM_ID | MIIM_STATE | MIIM_STRING;
mmi.fType = MFT_RADIOCHECK | MFT_STRING;
mmi.wID = DEVICERESCANID;
mmi.dwTypeData = TEXT("デバイス再検索");
mmi.cch = lstrlen(TEXT("デバイス再検索"));
InsertMenuItem(hSubMenu , GetMenuItemCount(hSubMenu) , TRUE , &mmi);
//新しいサブメニューに入れ替える
memset(&mmi , 0 , sizeof(mmi));
mmi.cbSize = sizeof(MENUITEMINFO);
mmi.fMask = MIIM_SUBMENU;
GetMenuItemInfo(hMenu , 2 , TRUE , &mmi);
mmi.hSubMenu = hSubMenu;
SetMenuItemInfo(hMenu , 2 , TRUE , &mmi);
SetMenu(hwnd , GetMenu(hwnd));
if(hOldSubMenu)DestroyMenu(hOldSubMenu);
return SelectDeviceID;
}
void GetPositionTimeString(TCHAR *lpOutString ,unsigned int nowtime,unsigned int mediatimes){
if(!lpOutString)return;
wsprintf(lpOutString , TEXT("%02u:%02u:%02u / %02u:%02u:%02u"),
nowtime/3600 , (nowtime%3600)/60 , (nowtime%3600)%60,
mediatimes/3600 , (mediatimes%3600)/60 , (mediatimes%3600)%60);
return;
}
void GetPositionTimeStringEx(TCHAR *lpOutString ,unsigned int nowtime,unsigned int mediatimes){
if(!lpOutString)return;
wsprintf(lpOutString , TEXT("%02u:%02u:%02u.%03u / %02u:%02u:%02u.%03u"),
(nowtime/1000)/3600 , ((nowtime/1000)%3600)/60 , ((nowtime/1000)%3600)%60,nowtime%1000,
(mediatimes/1000)/3600 , ((mediatimes/1000)%3600)/60 , ((mediatimes/1000)%3600)%60 , mediatimes%1000);
return;
}
void __stdcall mmTimerCallBack(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2){
PostMessage((HWND)dwUser , TIMER_REDRAW , 0 , 0);
}
void ConvNormalizeFromData(double *out , WAVEDN *lpOld , WAVEDN *lpPlay1 , WAVEDN *lpPlay2 , WaveFileInfo wfi){
WAVEDN *lpData[3] = { lpOld , lpPlay1 , lpPlay2 };
for (int i = 0; i < 3; i++)
{
WaveNormalize(lpData[i] ,
wfi.tagWaveFileBaseHeader.Fmt.tagPCMWaveFormat.wf.nAvgBytesPerSec ,
out + (i * wfi.tagWaveFileBaseHeader.Fmt.tagPCMWaveFormat.wf.nSamplesPerSec * wfi.tagWaveFileBaseHeader.Fmt.tagPCMWaveFormat.wf.nChannels) ,
&wfi.tagWaveFileBaseHeader.Fmt.tagPCMWaveFormat);
}
}
void WPV_DrawWave(HDC hdc, int sizex, int sizey, LPWaveFileBaseHeader lpHeader, double *lpData, int pos){
if(!lpHeader || !lpData)return;
int Channel = lpHeader->Fmt.tagPCMWaveFormat.wf.nChannels;
lpData += lpHeader->Fmt.tagPCMWaveFormat.wf.nSamplesPerSec * Channel;
lpData += pos * Channel;
HFONT hFont , hOldFont;
TCHAR string[32];
SIZE strSize;
if(!hdc)return;
hFont = MyFont(TEXT("メイリオ") , 48 , 0 , 0);
hOldFont = (HFONT)SelectObject(hdc , hFont);
CHSLine line(hdc);
SetBkMode(hdc ,TRANSPARENT);
int UseSamples =(int)(0.5 * lpHeader->Fmt.tagPCMWaveFormat.wf.nSamplesPerSec);
int start , end;
int startdrawx , dots;
int select_pos;
double data;
if(UseSamples%2)UseSamples++;
start = -UseSamples/2;
end = UseSamples/2 - 1;
if(Channel == 1){
wsprintf(string , TEXT("Mono"));
SetTextColor(hdc , RGB(191,255,127));
GetTextExtentPoint32(hdc , string , lstrlen(string) , &strSize);
TextOut(hdc , 5 , sizey/2 - strSize.cy/2 , string , lstrlen(string));
line.SetColor(191,255,127);
line.DrawEx(10 + strSize.cx , 0 , 10 + strSize.cx , sizey);
startdrawx = 10 + strSize.cx + 1;
dots = sizex - startdrawx;
for (int i = startdrawx; i < sizex; i++)
{
int posy;
select_pos = start + (int)((double)UseSamples * (i - startdrawx) / (dots - 1));
data = *(lpData + select_pos);
if(data < 0) posy = (int)((double)sizey/2 - (data * ((double)sizey/2 - 1.0)));
else posy = (int)((double)sizey/2 - (data * sizey/2));
if(i == startdrawx)line.SetPosition(i ,posy);
else line.Draw(i ,posy);
}
}else if(Channel == 2){
CHSLine line2(hdc);
line2.SetColor(127,191,255);
//区切り線
line.SetColor(255,255,255);
line.DrawEx(0,sizey/2 , sizex , sizey/2);
wsprintf(string , TEXT("Left"));
SetTextColor(hdc , RGB(255,191,127));
GetTextExtentPoint32(hdc , string , lstrlen(string) , &strSize);
TextOut(hdc , 5 , sizey/4 - strSize.cy/2 , string , lstrlen(string));
wsprintf(string , TEXT("Right"));
SetTextColor(hdc , RGB(127,191,255));
GetTextExtentPoint32(hdc , string , lstrlen(string) , &strSize);
TextOut(hdc , 5 , sizey/2 + sizey/4 - strSize.cy/2 , string , lstrlen(string));
line.DrawEx(10 + strSize.cx , 0 , 10 + strSize.cx , sizey);
line.SetColor(255,191,127);
startdrawx = 10 + strSize.cx + 1;
dots = sizex - startdrawx;
for (int i = startdrawx; i < sizex; i++)
{
int posy;
select_pos = start + (int)((double)UseSamples * (i - startdrawx) / (dots - 1));
data = *(lpData + select_pos * 2);
//data = ((i % 10) < 5) ? 1 : -1;
if(data < 0) posy = (int)((double)sizey/4 - (data * ((double)sizey/4 - 1)));
else posy = (int)((double)sizey/4 - (data * sizey/4));
if(i == startdrawx)line.SetPosition(i ,posy);
else line.Draw(i ,posy);
data = *(lpData + (select_pos * 2 + 1));
double tmpy;
if(data < 0) tmpy = ((double)sizey/4.0 - (data * ((double)sizey/4 - 2.0)));
else tmpy = ((double)sizey/4.0 - (data * sizey/4));
tmpy += sizey/2.0 + 1.0;
if(i == startdrawx)line2.SetPosition(i ,(int)tmpy);
else line2.Draw(i ,(int)tmpy);
}
}
SelectObject(hdc , hOldFont);
DeleteObject(hFont);
}
void WPV_DrawWaveABS(HDC hdc, int sizex, int sizey, LPWaveFileBaseHeader lpHeader, double *lpData, int pos){
if(!lpHeader || !lpData)return;
int Channel = lpHeader->Fmt.tagPCMWaveFormat.wf.nChannels;
lpData += lpHeader->Fmt.tagPCMWaveFormat.wf.nSamplesPerSec * Channel;
lpData += pos * Channel;
HFONT hFont , hOldFont;
TCHAR string[32];
SIZE strSize;
if(!hdc)return;
hFont = MyFont(TEXT("メイリオ") , 48 , 0 , 0);
hOldFont = (HFONT)SelectObject(hdc , hFont);
CHSLine line(hdc);
SetBkMode(hdc ,TRANSPARENT);
int UseSamples =(int)(0.5 * lpHeader->Fmt.tagPCMWaveFormat.wf.nSamplesPerSec);
int start , end;
int startdrawx , dots;
int select_pos;
double data;
if(UseSamples%2)UseSamples++;
start = -UseSamples/2;
end = UseSamples/2 - 1;
if(Channel == 1){
wsprintf(string , TEXT("Mono"));
SetTextColor(hdc , RGB(191,255,127));
GetTextExtentPoint32(hdc , string , lstrlen(string) , &strSize);
TextOut(hdc , 5 , sizey/2 - strSize.cy/2 , string , lstrlen(string));
line.SetColor(191,255,127);
line.DrawEx(10 + strSize.cx , 0 , 10 + strSize.cx , sizey);
startdrawx = 10 + strSize.cx + 1;
dots = sizex - startdrawx;
for (int i = startdrawx; i < sizex; i++)
{
int posy;
select_pos = start + (int)((double)UseSamples * (i - startdrawx) / (dots - 1));
data = *(lpData + select_pos);
if(data < 0) data *= -1;
posy = (int)((double)sizey - 1 - (data * ((double)sizey - 1)));
if(i == startdrawx)line.SetPosition(i ,posy);
else line.Draw(i ,posy);
}
}else if(Channel == 2){
CHSLine line2(hdc);
line2.SetColor(127,191,255);
//区切り線
line.SetColor(255,255,255);
line.DrawEx(0,sizey/2 , sizex , sizey/2);
wsprintf(string , TEXT("Left"));
SetTextColor(hdc , RGB(255,191,127));
GetTextExtentPoint32(hdc , string , lstrlen(string) , &strSize);
TextOut(hdc , 5 , sizey/4 - strSize.cy/2 , string , lstrlen(string));
wsprintf(string , TEXT("Right"));
SetTextColor(hdc , RGB(127,191,255));
GetTextExtentPoint32(hdc , string , lstrlen(string) , &strSize);
TextOut(hdc , 5 , sizey/2 + sizey/4 - strSize.cy/2 , string , lstrlen(string));
line.DrawEx(10 + strSize.cx , 0 , 10 + strSize.cx , sizey);
line.SetColor(255,191,127);
startdrawx = 10 + strSize.cx + 1;
dots = sizex - startdrawx;
for (int i = startdrawx; i < sizex; i++)
{
int posy;
select_pos = start + (int)((double)UseSamples * (i - startdrawx) / (dots - 1));
data = *(lpData + select_pos * 2);
if(data < 0) data *= -1;
posy = (int)((double)sizey/2 - 1 - (data * ((double)sizey/2 - 1)));
if(i == startdrawx)line.SetPosition(i ,posy);
else line.Draw(i ,posy);
data = *(lpData + (select_pos * 2 + 1));
if(data < 0) data *= -1;
posy = (int)((double)sizey - 1 - (data * ((double)sizey/2 - 2)));
if(i == startdrawx)line2.SetPosition(i ,posy);
else line2.Draw(i ,posy);
}
}
SelectObject(hdc , hOldFont);
DeleteObject(hFont);
}
void WPV_DrawPeekMeter(HDC hdc, int sizex, int sizey, LPWaveFileBaseHeader lpHeader, double *lpData, int pos){
if(!lpHeader || !lpData)return;
int Channel = lpHeader->Fmt.tagPCMWaveFormat.wf.nChannels;
lpData += lpHeader->Fmt.tagPCMWaveFormat.wf.nSamplesPerSec * Channel;
lpData += pos * Channel;
HFONT hFont , hOldFont;
TCHAR string[32];
SIZE strSize;
if(!hdc)return;
hFont = MyFont(TEXT("メイリオ") , 48 , 0 , 0);
hOldFont = (HFONT)SelectObject(hdc , hFont);
CHSLine line(hdc);
SetBkMode(hdc ,TRANSPARENT);
int UseSamples =(int)(0.001 * lpHeader->Fmt.tagPCMWaveFormat.wf.nSamplesPerSec);
int start , end;
int startdrawx , enddrawx , drawsizex , data_drawsizex;
double data;
if(UseSamples%2)UseSamples++;
start = -UseSamples/2;
end = UseSamples/2 - 1;
TCHAR textDecibel[20] = TEXT("-96.0dB");
if(Channel == 1){
wsprintf(string , TEXT("Mono"));
SetTextColor(hdc , RGB(191,255,127));
GetTextExtentPoint32(hdc , string , lstrlen(string) , &strSize);
TextOut(hdc , 5 , sizey/2 - strSize.cy/2 , string , lstrlen(string));
line.SetColor(191,255,127);
line.DrawEx(10 + strSize.cx , 0 , 10 + strSize.cx , sizey);
startdrawx = 10 + strSize.cx + 1;
GetTextExtentPoint32(hdc , textDecibel , lstrlen(textDecibel) , &strSize);
enddrawx = sizex - strSize.cx - 20;
drawsizex = enddrawx - startdrawx + 1;
//90,0.5,1
//149,1,1
double Peek = 0 , Decibel;
for (int pos = start; pos <= end; pos++)
{
data = *(lpData + pos);
if(data < 0) data *= -1;
if(Peek < data) Peek = data;
}
line.SetColor(191,255,127);
line.DrawEx(startdrawx + drawsizex + 10, 0 , startdrawx + drawsizex + 10,sizey);
if(Peek){
Decibel = 20 * log10(Peek);
if(Decibel > -MaxDecibel){
_stprintf_s(textDecibel , TEXT("%.1lfdB") , Decibel);
data_drawsizex = (int)(((Decibel + MaxDecibel) / MaxDecibel) * drawsizex);
double h ,s;
for (int i = 0; i < data_drawsizex; i++)
{
//h = 90 + ( (double)i / (drawsizex - 1) * 59);
//s = 0.5 + ( (double)i / (drawsizex - 1) * 0.5);
h = 150;
s = ( (double)i / (drawsizex - 1));
line.SetColorHSV(h,s,1);
line.DrawEx(startdrawx + i + 5 , 5 , startdrawx + i + 5 , sizey - 5);
}
}else _stprintf_s(textDecibel , TEXT("-∞dB"));
}else _stprintf_s(textDecibel , TEXT("-∞dB"));
SetTextColor(hdc , RGB(127,255,0));
SIZE dBtextSize;
GetTextExtentPoint32(hdc , textDecibel , lstrlen(textDecibel) , &dBtextSize);
TextOut(hdc , sizex - dBtextSize.cx, sizey/2 - strSize.cy/2 , textDecibel , lstrlen(textDecibel));
}else if(Channel == 2){
CHSLine line2(hdc);
line2.SetColor(127,191,255);
//区切り線
line.SetColor(255,255,255);
line.DrawEx(0,sizey/2 , sizex , sizey/2);
wsprintf(string , TEXT("Left"));
SetTextColor(hdc , RGB(255,191,127));
GetTextExtentPoint32(hdc , string , lstrlen(string) , &strSize);
TextOut(hdc , 5 , sizey/4 - strSize.cy/2 , string , lstrlen(string));
wsprintf(string , TEXT("Right"));
SetTextColor(hdc , RGB(127,191,255));
GetTextExtentPoint32(hdc , string , lstrlen(string) , &strSize);
TextOut(hdc , 5 , sizey/2 + sizey/4 - strSize.cy/2 , string , lstrlen(string));
line.DrawEx(10 + strSize.cx , 0 , 10 + strSize.cx , sizey);
line.SetColor(255,191,127);
startdrawx = 10 + strSize.cx + 1;
GetTextExtentPoint32(hdc , textDecibel , lstrlen(textDecibel) , &strSize);
enddrawx = sizex - strSize.cx - 20;
drawsizex = enddrawx - startdrawx + 1;
double Peek[2] = { 0 , 0} , Decibel;
for (int pos = start; pos <= end; pos++)
{
data = *(lpData + pos*2);
if(data < 0) data *= -1;
if(Peek[0] < data) Peek[0] = data;
data = *(lpData + pos*2 + 1);
if(data < 0) data *= -1;
if(Peek[1] < data) Peek[1] = data;
}
line.SetColor(255,255,255);
line.DrawEx(startdrawx + drawsizex + 10, 0 , startdrawx + drawsizex + 10,sizey);
if(Peek[0]){
Decibel = 20 * log10(Peek[0]);
if(Decibel > -MaxDecibel){
_stprintf_s(textDecibel , TEXT("%.1lfdB") , Decibel);
data_drawsizex = (int)(((Decibel + MaxDecibel) / MaxDecibel) * drawsizex);
double h ,s;
for (int i = 0; i < data_drawsizex; i++)
{
h = 30;
s = ( (double)i / (drawsizex - 1));
line.SetColorHSV(h,s,1);
line.DrawEx(startdrawx + i + 5 , 5 , startdrawx + i + 5 , sizey/2 - 5);
}
}else _stprintf_s(textDecibel , TEXT("-∞dB"));
}else _stprintf_s(textDecibel , TEXT("-∞dB"));
SetTextColor(hdc , RGB(255,127,0));
SIZE dBtextSize;
GetTextExtentPoint32(hdc , textDecibel , lstrlen(textDecibel) , &dBtextSize);
TextOut(hdc , sizex - dBtextSize.cx, sizey/4 - strSize.cy/2 , textDecibel , lstrlen(textDecibel));
if(Peek[1]){
Decibel = 20 * log10(Peek[1]);
if(Decibel > -MaxDecibel){
_stprintf_s(textDecibel , TEXT("%.1lfdB") , Decibel);
data_drawsizex = (int)(((Decibel + MaxDecibel) / MaxDecibel) * drawsizex);
double h ,s;
for (int i = 0; i < data_drawsizex; i++)
{
h = 180;
s = ( (double)i / (drawsizex - 1));
line.SetColorHSV(h,s,1);
line.DrawEx(startdrawx + i + 5 , sizey/2 + 6 , startdrawx + i + 5 , sizey - 5);
}
}else _stprintf_s(textDecibel , TEXT("-∞dB"));
}else _stprintf_s(textDecibel , TEXT("-∞dB"));
SetTextColor(hdc , RGB(0,255,255));
GetTextExtentPoint32(hdc , textDecibel , lstrlen(textDecibel) , &dBtextSize);
TextOut(hdc , sizex - dBtextSize.cx, sizey/2 + sizey/4 - strSize.cy/2 , textDecibel , lstrlen(textDecibel));
}
SelectObject(hdc , hOldFont);
DeleteObject(hFont);
}
void WPV_DrawVUMeter(HDC hdc, int sizex, int sizey, LPWaveFileBaseHeader lpHeader, double *lpData, int pos){
if(!lpHeader || !lpData)return;
int Channel = lpHeader->Fmt.tagPCMWaveFormat.wf.nChannels;
lpData += lpHeader->Fmt.tagPCMWaveFormat.wf.nSamplesPerSec * Channel;
lpData += pos * Channel;
HFONT hFont , hOldFont;
TCHAR string[32];
SIZE strSize;
if(!hdc)return;
hFont = MyFont(TEXT("メイリオ") , 48 , 0 , 0);
hOldFont = (HFONT)SelectObject(hdc , hFont);
CHSLine line(hdc);
SetBkMode(hdc ,TRANSPARENT);
int UseSamples =(int)(0.3 * lpHeader->Fmt.tagPCMWaveFormat.wf.nSamplesPerSec);
int start , end;
int startdrawx , enddrawx , drawsizex , data_drawsizex;
double data;
if(UseSamples%2)UseSamples++;
start = -UseSamples/2;
end = UseSamples/2 - 1;
TCHAR textDecibel[20] = TEXT("-96.0dB");
if(Channel == 1){
wsprintf(string , TEXT("Mono"));
SetTextColor(hdc , RGB(191,255,127));
GetTextExtentPoint32(hdc , string , lstrlen(string) , &strSize);
TextOut(hdc , 5 , sizey/2 - strSize.cy/2 , string , lstrlen(string));
line.SetColor(191,255,127);
line.DrawEx(10 + strSize.cx , 0 , 10 + strSize.cx , sizey);
startdrawx = 10 + strSize.cx + 1;
GetTextExtentPoint32(hdc , textDecibel , lstrlen(textDecibel) , &strSize);
enddrawx = sizex - strSize.cx - 20;
drawsizex = enddrawx - startdrawx + 1;
//90,0.5,1
//149,1,1
double Average = 0 , Decibel;
for (int pos = start; pos <= end; pos++)
{
data = *(lpData + pos);
if(data >= 0)
Average += data;
else
Average -= data;
}
Average /= UseSamples;
line.SetColor(191,255,127);
line.DrawEx(startdrawx + drawsizex + 10, 0 , startdrawx + drawsizex + 10,sizey);
if(Average){
Decibel = 20 * log10(Average);
if(Decibel > -MaxDecibel){
_stprintf_s(textDecibel , TEXT("%.1lfdB") , Decibel);
data_drawsizex = (int)(((Decibel + MaxDecibel) / MaxDecibel) * drawsizex);
double h ,s;
for (int i = 0; i < data_drawsizex; i++)
{
//h = 90 + ( (double)i / (drawsizex - 1) * 59);
//s = 0.5 + ( (double)i / (drawsizex - 1) * 0.5);
h = 150;
s = ( (double)i / (drawsizex - 1));
line.SetColorHSV(h,s,1);
line.DrawEx(startdrawx + i + 5 , 5 , startdrawx + i + 5 , sizey - 5);
}
}else _stprintf_s(textDecibel , TEXT("-∞dB"));
}else _stprintf_s(textDecibel , TEXT("-∞dB"));
SetTextColor(hdc , RGB(127,255,0));
SIZE dBtextSize;
GetTextExtentPoint32(hdc , textDecibel , lstrlen(textDecibel) , &dBtextSize);
TextOut(hdc , sizex - dBtextSize.cx, sizey/2 - strSize.cy/2 , textDecibel , lstrlen(textDecibel));
}else if(Channel == 2){
CHSLine line2(hdc);
line2.SetColor(127,191,255);
//区切り線
line.SetColor(255,255,255);
line.DrawEx(0,sizey/2 , sizex , sizey/2);
wsprintf(string , TEXT("Left"));
SetTextColor(hdc , RGB(255,191,127));
GetTextExtentPoint32(hdc , string , lstrlen(string) , &strSize);
TextOut(hdc , 5 , sizey/4 - strSize.cy/2 , string , lstrlen(string));
wsprintf(string , TEXT("Right"));
SetTextColor(hdc , RGB(127,191,255));
GetTextExtentPoint32(hdc , string , lstrlen(string) , &strSize);
TextOut(hdc , 5 , sizey/2 + sizey/4 - strSize.cy/2 , string , lstrlen(string));
line.DrawEx(10 + strSize.cx , 0 , 10 + strSize.cx , sizey);
line.SetColor(255,191,127);
startdrawx = 10 + strSize.cx + 1;
GetTextExtentPoint32(hdc , textDecibel , lstrlen(textDecibel) , &strSize);
enddrawx = sizex - strSize.cx - 20;
drawsizex = enddrawx - startdrawx + 1;
double Average[2] = { 0 , 0} , Decibel;
for (int pos = start; pos <= end; pos++)
{
data = *(lpData + pos*2);
if(data >= 0)
Average[0] += data;
else
Average[0] -= data;
data = *(lpData + pos*2 + 1);
if(data >= 0)
Average[1] += data;
else
Average[1] -= data;
}
Average[0] /= UseSamples;
Average[1] /= UseSamples;
line.SetColor(255,255,255);
line.DrawEx(startdrawx + drawsizex + 10, 0 , startdrawx + drawsizex + 10,sizey);
if(Average[0]){
Decibel = 20 * log10(Average[0]);
if(Decibel > -MaxDecibel){
_stprintf_s(textDecibel , TEXT("%.1lfdB") , Decibel);
data_drawsizex = (int)(((Decibel + MaxDecibel) / MaxDecibel) * drawsizex);
double h ,s;
for (int i = 0; i < data_drawsizex; i++)
{
h = 30;
s = ( (double)i / (drawsizex - 1));
line.SetColorHSV(h,s,1);
line.DrawEx(startdrawx + i + 5 , 5 , startdrawx + i + 5 , sizey/2 - 5);
}
}else _stprintf_s(textDecibel , TEXT("-∞dB"));
}else _stprintf_s(textDecibel , TEXT("-∞dB"));
SetTextColor(hdc , RGB(255,127,0));
SIZE dBtextSize;
GetTextExtentPoint32(hdc , textDecibel , lstrlen(textDecibel) , &dBtextSize);
TextOut(hdc , sizex - dBtextSize.cx, sizey/4 - strSize.cy/2 , textDecibel , lstrlen(textDecibel));
if(Average[1]){
Decibel = 20 * log10(Average[1]);
if(Decibel > -MaxDecibel){
_stprintf_s(textDecibel , TEXT("%.1lfdB") , Decibel);
data_drawsizex = (int)(((Decibel + MaxDecibel) / MaxDecibel) * drawsizex);
double h ,s;
for (int i = 0; i < data_drawsizex; i++)
{
h = 180;
s = ( (double)i / (drawsizex - 1));
line.SetColorHSV(h,s,1);
line.DrawEx(startdrawx + i + 5 , sizey/2 + 6 , startdrawx + i + 5 , sizey - 5);
}
}else _stprintf_s(textDecibel , TEXT("-∞dB"));
}else _stprintf_s(textDecibel , TEXT("-∞dB"));
SetTextColor(hdc , RGB(0,255,255));
GetTextExtentPoint32(hdc , textDecibel , lstrlen(textDecibel) , &dBtextSize);
TextOut(hdc , sizex - dBtextSize.cx, sizey/2 + sizey/4 - strSize.cy/2 , textDecibel , lstrlen(textDecibel));
}
SelectObject(hdc , hOldFont);
DeleteObject(hFont);
}
void WPV_DrawVUMeter2(HDC hdc, int sizex, int sizey, LPWaveFileBaseHeader lpHeader, double *lpData, int pos){
if(!lpHeader || !lpData)return;
int Channel = lpHeader->Fmt.tagPCMWaveFormat.wf.nChannels;
lpData += lpHeader->Fmt.tagPCMWaveFormat.wf.nSamplesPerSec * Channel;
lpData += pos * Channel;
HFONT hFont , hOldFont;
TCHAR string[32];
SIZE strSize;
if(!hdc)return;
hFont = MyFont(TEXT("メイリオ") , 48 , 0 , 0);
hOldFont = (HFONT)SelectObject(hdc , hFont);
CHSLine line(hdc);
SetBkMode(hdc ,TRANSPARENT);
int UseSamples =(int)(0.3 * lpHeader->Fmt.tagPCMWaveFormat.wf.nSamplesPerSec);
int start , end;
int startdrawx , enddrawx , drawsizex , data_drawsizex;
double data;
if(UseSamples%2)UseSamples++;
start = -UseSamples/2;
end = UseSamples/2 - 1;
TCHAR textDecibel[20] = TEXT("-96.0dB");
if(Channel == 1){
wsprintf(string , TEXT("Mono"));
SetTextColor(hdc , RGB(191,255,127));
GetTextExtentPoint32(hdc , string , lstrlen(string) , &strSize);
TextOut(hdc , 5 , sizey/2 - strSize.cy/2 , string , lstrlen(string));
line.SetColor(191,255,127);
line.DrawEx(10 + strSize.cx , 0 , 10 + strSize.cx , sizey);
startdrawx = 10 + strSize.cx + 1;
GetTextExtentPoint32(hdc , textDecibel , lstrlen(textDecibel) , &strSize);
enddrawx = sizex - strSize.cx - 20;
drawsizex = enddrawx - startdrawx + 1;
//90,0.5,1
//149,1,1
double Average = 0 , Decibel;
for (int pos = start; pos <= end; pos++)
{
data = *(lpData + pos);
if(data >= 0)
Average += data;
else
Average -= data;
}
Average /= UseSamples;
line.SetColor(191,255,127);
line.DrawEx(startdrawx + drawsizex + 10, 0 , startdrawx + drawsizex + 10,sizey);
double data , h ,s;
if(Average){
Decibel = 20 * log10(Average);
if(Decibel > -MaxDecibel){
_stprintf_s(textDecibel , TEXT("%.1lfdB") , Decibel);
data = (Decibel + MaxDecibel) / MaxDecibel;
data_drawsizex = (int)(((Decibel + MaxDecibel) / MaxDecibel) * drawsizex);
for (int i = 0; i < data_drawsizex; i++)
{
h = 120 - ( (double)i / (drawsizex - 1)) * 120;
s = 0.75;
line.SetColorHSV(h,s,1);
line.DrawEx(startdrawx + i + 5 , 5 , startdrawx + i + 5 , sizey - 5);
}
}else _stprintf_s(textDecibel , TEXT("-∞dB"));
}else _stprintf_s(textDecibel , TEXT("-∞dB"));
SetTextColor(hdc , RGB(127,255,0));
SIZE dBtextSize;
GetTextExtentPoint32(hdc , textDecibel , lstrlen(textDecibel) , &dBtextSize);
TextOut(hdc , sizex - dBtextSize.cx, sizey/2 - strSize.cy/2 , textDecibel , lstrlen(textDecibel));
}else if(Channel == 2){
CHSLine line2(hdc);
line2.SetColor(127,191,255);
//区切り線
line.SetColor(255,255,255);
line.DrawEx(0,sizey/2 , sizex , sizey/2);
wsprintf(string , TEXT("Left"));
SetTextColor(hdc , RGB(255,191,127));
GetTextExtentPoint32(hdc , string , lstrlen(string) , &strSize);
TextOut(hdc , 5 , sizey/4 - strSize.cy/2 , string , lstrlen(string));
wsprintf(string , TEXT("Right"));
SetTextColor(hdc , RGB(127,191,255));
GetTextExtentPoint32(hdc , string , lstrlen(string) , &strSize);
TextOut(hdc , 5 , sizey/2 + sizey/4 - strSize.cy/2 , string , lstrlen(string));
line.DrawEx(10 + strSize.cx , 0 , 10 + strSize.cx , sizey);
line.SetColor(255,191,127);
startdrawx = 10 + strSize.cx + 1;
GetTextExtentPoint32(hdc , textDecibel , lstrlen(textDecibel) , &strSize);
enddrawx = sizex - strSize.cx - 20;
drawsizex = enddrawx - startdrawx + 1;
double Average[2] = { 0 , 0} , Decibel;
for (int pos = start; pos <= end; pos++)
{
data = *(lpData + pos*2);
if(data >= 0)
Average[0] += data;
else
Average[0] -= data;
data = *(lpData + pos*2 + 1);
if(data >= 0)
Average[1] += data;
else
Average[1] -= data;
}
Average[0] /= UseSamples;
Average[1] /= UseSamples;
line.SetColor(255,255,255);
line.DrawEx(startdrawx + drawsizex + 10, 0 , startdrawx + drawsizex + 10,sizey);
double data;
if(Average[0]){
Decibel = 20 * log10(Average[0]);
if(Decibel > -MaxDecibel){
_stprintf_s(textDecibel , TEXT("%.1lfdB") , Decibel);
data = (Decibel + MaxDecibel) / MaxDecibel;
data_drawsizex = (int)(((Decibel + MaxDecibel) / MaxDecibel) * drawsizex);
double h ,s;
for (int i = 0; i < data_drawsizex; i++)
{
h = 120 - ( (double)i / (drawsizex - 1)) * 120;
s = 0.75;
line.SetColorHSV(h,s,1);
line.DrawEx(startdrawx + i + 5 , 5 , startdrawx + i + 5 , sizey/2 - 5);
}
}else _stprintf_s(textDecibel , TEXT("-∞dB"));
}else _stprintf_s(textDecibel , TEXT("-∞dB"));
SetTextColor(hdc , RGB(255,127,0));
SIZE dBtextSize;
GetTextExtentPoint32(hdc , textDecibel , lstrlen(textDecibel) , &dBtextSize);
TextOut(hdc , sizex - dBtextSize.cx, sizey/4 - strSize.cy/2 , textDecibel , lstrlen(textDecibel));
if(Average[1]){
Decibel = 20 * log10(Average[1]);
if(Decibel > -MaxDecibel){
_stprintf_s(textDecibel , TEXT("%.1lfdB") , Decibel);
data = (Decibel + MaxDecibel) / MaxDecibel;
data_drawsizex = (int)(((Decibel + MaxDecibel) / MaxDecibel) * drawsizex);
double h ,s;
for (int i = 0; i < data_drawsizex; i++)
{
h = 120 - ( (double)i / (drawsizex - 1)) * 120;
s = 0.75;
line2.SetColorHSV(h,s,1);
line2.DrawEx(startdrawx + i + 5 , sizey/2 + 6 , startdrawx + i + 5 , sizey - 5);
}
}else _stprintf_s(textDecibel , TEXT("-∞dB"));
}else _stprintf_s(textDecibel , TEXT("-∞dB"));
SetTextColor(hdc , RGB(0,255,255));
GetTextExtentPoint32(hdc , textDecibel , lstrlen(textDecibel) , &dBtextSize);
TextOut(hdc , sizex - dBtextSize.cx, sizey/2 + sizey/4 - strSize.cy/2 , textDecibel , lstrlen(textDecibel));
}
SelectObject(hdc , hOldFont);
DeleteObject(hFont);
}
void WPV_SpectrumWave(HDC hdc, int sizex, int sizey, LPWaveFileBaseHeader lpHeader, double *lpData, int pos){
if(!lpHeader || !lpData)return;
int Channel = lpHeader->Fmt.tagPCMWaveFormat.wf.nChannels;
lpData += lpHeader->Fmt.tagPCMWaveFormat.wf.nSamplesPerSec * Channel;
lpData += pos * Channel;
HFONT hFont , hOldFont;
TCHAR string[32];
SIZE strSize;
if(!hdc)return;
hFont = MyFont(TEXT("メイリオ") , 48 , 0 , 0);
hOldFont = (HFONT)SelectObject(hdc , hFont);
CHSLine line(hdc);
SetBkMode(hdc ,TRANSPARENT);
int UseSamples = 8192;
int start , end;
int startdrawx , dots;
if(UseSamples%2)UseSamples++;
start = -UseSamples/2;
end = UseSamples/2 - 1;
if(Channel == 1){
wsprintf(string , TEXT("Mono"));
SetTextColor(hdc , RGB(191,255,127));
GetTextExtentPoint32(hdc , string , lstrlen(string) , &strSize);
TextOut(hdc , 5 , sizey/2 - strSize.cy/2 , string , lstrlen(string));
line.SetColor(191,255,127);
line.DrawEx(10 + strSize.cx , 0 , 10 + strSize.cx , sizey);
startdrawx = 10 + strSize.cx + 1;
dots = sizex - startdrawx;
LPHSFFT_CMPLEX lpCmp = (LPHSFFT_CMPLEX)HeapAlloc(GetProcessHeap() , HEAP_ZERO_MEMORY , UseSamples * sizeof(HSFFT_CMPLEX)) ;
HS_rfft_exec(lpData + start , lpCmp , UseSamples);
//振幅スペクトルを求めながら最大値を求める
double maxdata = 0;
for (int i = 0; i <= UseSamples/2 ; i++)
{
(lpCmp + i)->Real = sqrt(pow((lpCmp + i)->Real , 2) + pow((lpCmp + i)->Imaginary , 2));
if(maxdata < (lpCmp + i)->Real) maxdata = (lpCmp + i)->Real;
}
//最大値で振幅スペクトルを0.0~1.0に正規化する
for (int i = 0; i <= UseSamples/2; i++)
{
(lpCmp + i)->Real /= maxdata;
}
UseSamples /= 2;
UseSamples++;
//表示スペース分にまとめる
int mixdatanums , restdatanums;
double *pData , data;
mixdatanums = UseSamples / (dots - 1) ;
restdatanums = UseSamples % (dots - 1) ;
for (int i = 0; i <= dots; i++)
{
pData = &(lpCmp + i)->Imaginary;
*pData = 0;
for (int j = 0; j < ((i == dots) ? restdatanums : mixdatanums); j++)
{
*pData += (lpCmp + i*mixdatanums + j)->Real;
}
*pData /= mixdatanums;
if(*pData){
*pData = 20 * log10(*pData);
}else{
*pData = -MaxDecibel - 1;
}
}
//描画する
for (int i = startdrawx , pos = 0; i < sizex; i++ , pos++)
{
pData = &(lpCmp + pos)->Imaginary;
if(*pData > -MaxDecibel){
data = (*pData + MaxDecibel) / MaxDecibel;
data *= sizey - 1;
data = sizey - 1 - data;
if(i == startdrawx)line.SetPosition(i , (int)data);
else line.Draw(i , (int)data);
}else {
if(i == startdrawx) line.SetPosition(i , sizey - 1);
else line.Draw(i , sizey - 1);
}
}
HeapFree(GetProcessHeap() , NULL , lpCmp);
}else if(Channel == 2){
CHSLine line2(hdc);
line2.SetColor(127,191,255);
//区切り線
line.SetColor(255,255,255);
line.DrawEx(0,sizey/2 , sizex , sizey/2);
wsprintf(string , TEXT("Left"));
SetTextColor(hdc , RGB(255,191,127));
GetTextExtentPoint32(hdc , string , lstrlen(string) , &strSize);
TextOut(hdc , 5 , sizey/4 - strSize.cy/2 , string , lstrlen(string));
wsprintf(string , TEXT("Right"));
SetTextColor(hdc , RGB(127,191,255));
GetTextExtentPoint32(hdc , string , lstrlen(string) , &strSize);
TextOut(hdc , 5 , sizey/2 + sizey/4 - strSize.cy/2 , string , lstrlen(string));
line.DrawEx(10 + strSize.cx , 0 , 10 + strSize.cx , sizey);
line.SetColor(255,191,127);
startdrawx = 10 + strSize.cx + 1;
dots = sizex - startdrawx;
LPHSFFT_CMPLEX lpCmp[2] ;
lpCmp[0] = (LPHSFFT_CMPLEX)HeapAlloc(GetProcessHeap() , HEAP_ZERO_MEMORY , UseSamples * sizeof(HSFFT_CMPLEX)) ;
lpCmp[1] = (LPHSFFT_CMPLEX)HeapAlloc(GetProcessHeap() , HEAP_ZERO_MEMORY , UseSamples * sizeof(HSFFT_CMPLEX)) ;
//FFT実行ブロック
{
double *base[2];
base[0] = (double*)HeapAlloc(GetProcessHeap() , HEAP_ZERO_MEMORY , UseSamples * sizeof(double)) ;
base[1] = (double*)HeapAlloc(GetProcessHeap() , HEAP_ZERO_MEMORY , UseSamples * sizeof(double)) ;
WaveCutChannel(lpData + start * 2 , UseSamples * 2 * sizeof(double) , base[0] , base[1] , 64);
HS_rfft_exec(base[0] , lpCmp[0] , UseSamples);
HS_rfft_exec(base[1] , lpCmp[1] , UseSamples);
HeapFree(GetProcessHeap() , NULL , base[0]);
HeapFree(GetProcessHeap() , NULL , base[1]);
}
UseSamples /= 2;
UseSamples++;
int mixdatanums , restdatanums;
mixdatanums = UseSamples / (dots - 1) ;
restdatanums = UseSamples % (dots - 1) ;
double *pData , data;
for (int h = 0; h < 2; h++)
{
//振幅スペクトルを求めながら最大値を求める
double maxdata = 0;
for (int i = 0; i <= UseSamples ; i++)
{
(lpCmp[h] + i)->Real = sqrt(pow((lpCmp[h] + i)->Real , 2) + pow((lpCmp[h] + i)->Imaginary , 2));
if(maxdata < (lpCmp[h] + i)->Real) maxdata = (lpCmp[h] + i)->Real;
}
//最大値で振幅スペクトルを0.0~1.0に正規化する
for (int i = 0; i <= UseSamples; i++)
{
(lpCmp[h] + i)->Real /= maxdata;
}
//表示スペース分にまとめる
for (int i = 0; i <= dots; i++)
{
pData = &(lpCmp[h] + i)->Imaginary;
*pData = 0;
for (int j = 0; j < ((i == dots) ? restdatanums : mixdatanums); j++)
{
*pData += (lpCmp[h] + i*mixdatanums + j)->Real;
}
*pData /= mixdatanums;
if(*pData){
*pData = 20 * log10(*pData);
}else{
*pData = -MaxDecibel - 1;
}
}
}
//描画する
for (int i = startdrawx , pos = 0; i < sizex; i++ , pos++)
{
pData = &(lpCmp[0] + pos)->Imaginary;
if(*pData > -MaxDecibel){
data = (*pData + MaxDecibel) / MaxDecibel;
data *= sizey/2 - 1;
data = sizey/2 - 1 - data;
if(i == startdrawx)line.SetPosition(i , (int)data);
else line.Draw(i , (int)data);
}else{
if(i == startdrawx) line.SetPosition(i , sizey/2 - 1);
else line.Draw(i , sizey/2 - 1);
}
pData = &(lpCmp[1] + pos)->Imaginary;
if(*pData > -MaxDecibel){
data = (*pData + MaxDecibel) / MaxDecibel;
data *= sizey/2 - 2;
data = sizey - 1 - data;
if(i == startdrawx)line2.SetPosition(i , (int)data);
else line2.Draw(i , (int)data);
}else{
if(i == startdrawx) line2.SetPosition(i , sizey - 1);
else line2.Draw(i , sizey - 1);
}
}
HeapFree(GetProcessHeap() , NULL , lpCmp[0]);
HeapFree(GetProcessHeap() , NULL , lpCmp[1]);
}
SelectObject(hdc , hOldFont);
DeleteObject(hFont);
}
void WPV_SpectrumWave2(HDC hdc, int sizex, int sizey, LPWaveFileBaseHeader lpHeader, double *lpData, int pos){
if(!lpHeader || !lpData)return;
int Channel = lpHeader->Fmt.tagPCMWaveFormat.wf.nChannels;
lpData += lpHeader->Fmt.tagPCMWaveFormat.wf.nSamplesPerSec * Channel;
lpData += pos * Channel;
HFONT hFont , hOldFont;
TCHAR string[32];
SIZE strSize;
if(!hdc)return;
hFont = MyFont(TEXT("メイリオ") , 48 , 0 , 0);
hOldFont = (HFONT)SelectObject(hdc , hFont);
CHSLine line(hdc);
SetBkMode(hdc ,TRANSPARENT);
int UseSamples = 8192;
int start , end;
int startdrawx , dots;
if(UseSamples%2)UseSamples++;
start = -UseSamples/2;
end = UseSamples/2 - 1;
if(Channel == 1){
wsprintf(string , TEXT("Mono"));
SetTextColor(hdc , RGB(191,255,127));
GetTextExtentPoint32(hdc , string , lstrlen(string) , &strSize);
TextOut(hdc , 5 , sizey/2 - strSize.cy/2 , string , lstrlen(string));
line.SetColor(191,255,127);
line.DrawEx(10 + strSize.cx , 0 , 10 + strSize.cx , sizey);
startdrawx = 10 + strSize.cx + 1;
dots = sizex - startdrawx;
LPHSFFT_CMPLEX lpCmp = (LPHSFFT_CMPLEX)HeapAlloc(GetProcessHeap() , HEAP_ZERO_MEMORY , UseSamples * sizeof(HSFFT_CMPLEX)) ;
HS_rfft_exec(lpData + start , lpCmp , UseSamples);
//振幅スペクトルを求めながら最大値を求める
double maxdata = 0;
for (int i = 0; i <= UseSamples/2 ; i++)
{
(lpCmp + i)->Real = sqrt(pow((lpCmp + i)->Real , 2) + pow((lpCmp + i)->Imaginary , 2));
if(maxdata < (lpCmp + i)->Real) maxdata = (lpCmp + i)->Real;
}
//最大値で振幅スペクトルを0.0~1.0に正規化する
for (int i = 0; i <= UseSamples/2; i++)
{
(lpCmp + i)->Real /= maxdata;
}
UseSamples /= 2;
UseSamples++;
//表示スペース分にまとめる
int mixdatanums , restdatanums;
double *pData , data;
mixdatanums = UseSamples / (dots - 1) ;
restdatanums = UseSamples % (dots - 1) ;
for (int i = 0; i <= dots; i++)
{
pData = &(lpCmp + i)->Imaginary;
*pData = 0;
for (int j = 0; j < ((i == dots) ? restdatanums : mixdatanums); j++)
{
*pData += (lpCmp + i*mixdatanums + j)->Real;
}
*pData /= mixdatanums;
if(*pData){
*pData = 20 * log10(*pData);
}else{
*pData = -MaxDecibel - 1;
}
}
//描画する
for (int i = startdrawx , pos = 0; i < sizex; i++ , pos++)
{
pData = &(lpCmp + pos)->Imaginary;
if(*pData > -MaxDecibel){
data = (*pData + MaxDecibel) / MaxDecibel;
data *= sizey - 1;
data = sizey - 1 - data;
line.SetPosition(i , sizey-1);
line.Draw(i , (int)data);
}
}
HeapFree(GetProcessHeap() , NULL , lpCmp);
}else if(Channel == 2){
CHSLine line2(hdc);
line2.SetColor(127,191,255);
//区切り線
line.SetColor(255,255,255);
line.DrawEx(0,sizey/2 , sizex , sizey/2);
wsprintf(string , TEXT("Left"));
SetTextColor(hdc , RGB(255,191,127));
GetTextExtentPoint32(hdc , string , lstrlen(string) , &strSize);
TextOut(hdc , 5 , sizey/4 - strSize.cy/2 , string , lstrlen(string));
wsprintf(string , TEXT("Right"));
SetTextColor(hdc , RGB(127,191,255));
GetTextExtentPoint32(hdc , string , lstrlen(string) , &strSize);
TextOut(hdc , 5 , sizey/2 + sizey/4 - strSize.cy/2 , string , lstrlen(string));
line.DrawEx(10 + strSize.cx , 0 , 10 + strSize.cx , sizey);
line.SetColor(255,191,127);
startdrawx = 10 + strSize.cx + 1;
dots = sizex - startdrawx;
LPHSFFT_CMPLEX lpCmp[2] ;
lpCmp[0] = (LPHSFFT_CMPLEX)HeapAlloc(GetProcessHeap() , HEAP_ZERO_MEMORY , UseSamples * sizeof(HSFFT_CMPLEX)) ;
lpCmp[1] = (LPHSFFT_CMPLEX)HeapAlloc(GetProcessHeap() , HEAP_ZERO_MEMORY , UseSamples * sizeof(HSFFT_CMPLEX)) ;
//FFT実行ブロック
{
double *base[2];
base[0] = (double*)HeapAlloc(GetProcessHeap() , HEAP_ZERO_MEMORY , UseSamples * sizeof(double)) ;
base[1] = (double*)HeapAlloc(GetProcessHeap() , HEAP_ZERO_MEMORY , UseSamples * sizeof(double)) ;
WaveCutChannel(lpData + start * 2 , UseSamples * 2 * sizeof(double) , base[0] , base[1] , 64);
HS_rfft_exec(base[0] , lpCmp[0] , UseSamples);
HS_rfft_exec(base[1] , lpCmp[1] , UseSamples);
HeapFree(GetProcessHeap() , NULL , base[0]);
HeapFree(GetProcessHeap() , NULL , base[1]);
}
UseSamples /= 2;
UseSamples++;
int mixdatanums , restdatanums;
mixdatanums = UseSamples / (dots - 1) ;
restdatanums = UseSamples % (dots - 1) ;
double *pData , data;
for (int h = 0; h < 2; h++)
{
//振幅スペクトルを求めながら最大値を求める
double maxdata = 0;
for (int i = 0; i <= UseSamples ; i++)
{
(lpCmp[h] + i)->Real = sqrt(pow((lpCmp[h] + i)->Real , 2) + pow((lpCmp[h] + i)->Imaginary , 2));
if(maxdata < (lpCmp[h] + i)->Real) maxdata = (lpCmp[h] + i)->Real;
}
//最大値で振幅スペクトルを0.0~1.0に正規化する
for (int i = 0; i <= UseSamples; i++)
{
(lpCmp[h] + i)->Real /= maxdata;
}
//表示スペース分にまとめる
for (int i = 0; i <= dots; i++)
{
pData = &(lpCmp[h] + i)->Imaginary;
*pData = 0;
for (int j = 0; j < ((i == dots) ? restdatanums : mixdatanums); j++)
{
*pData += (lpCmp[h] + i*mixdatanums + j)->Real;
}
*pData /= mixdatanums;
if(*pData){
*pData = 20 * log10(*pData);
}else{
*pData = -MaxDecibel - 1;
}
}
}
//描画する
for (int i = startdrawx , pos = 0; i < sizex; i++ , pos++)
{
pData = &(lpCmp[0] + pos)->Imaginary;
if(*pData > -MaxDecibel){
data = (*pData + MaxDecibel) / MaxDecibel;
data *= sizey/2 - 1;
data = sizey/2 - 1 - data;
line.SetPosition(i , sizey/2 - 1);
line.Draw(i , (int)data);
}
pData = &(lpCmp[1] + pos)->Imaginary;
if(*pData > -MaxDecibel){
data = (*pData + MaxDecibel) / MaxDecibel;
data *= sizey/2 - 2;
data = sizey - 1 - data;
line2.SetPosition(i , sizey - 1);
line2.Draw(i , (int)data);
}
}
HeapFree(GetProcessHeap() , NULL , lpCmp[0]);
HeapFree(GetProcessHeap() , NULL , lpCmp[1]);
}
SelectObject(hdc , hOldFont);
DeleteObject(hFont);
}
void WPV_SpectrumWave3(HDC hdc, int sizex, int sizey, LPWaveFileBaseHeader lpHeader, double *lpData, int pos){
if(!lpHeader || !lpData)return;
int Channel = lpHeader->Fmt.tagPCMWaveFormat.wf.nChannels;
lpData += lpHeader->Fmt.tagPCMWaveFormat.wf.nSamplesPerSec * Channel;
lpData += pos * Channel;
HFONT hFont , hOldFont;
TCHAR string[32];
SIZE strSize;
if(!hdc)return;
hFont = MyFont(TEXT("メイリオ") , 48 , 0 , 0);
hOldFont = (HFONT)SelectObject(hdc , hFont);
CHSLine line(hdc);
CHSLine line_white(hdc);
line_white.SetColor(255,255,255);
SetBkMode(hdc ,TRANSPARENT);
int UseSamples = 8192;
int start , end;
int startdrawx , dots;
if(UseSamples%2)UseSamples++;
start = -UseSamples/2;
end = UseSamples/2 - 1;
if(Channel == 1){
wsprintf(string , TEXT("Mono"));
SetTextColor(hdc , RGB(191,255,127));
GetTextExtentPoint32(hdc , string , lstrlen(string) , &strSize);
TextOut(hdc , 5 , sizey/2 - strSize.cy/2 , string , lstrlen(string));
line.SetColor(191,255,127);
line.DrawEx(10 + strSize.cx , 0 , 10 + strSize.cx , sizey);
startdrawx = 10 + strSize.cx + 1;
dots = sizex - startdrawx;
LPHSFFT_CMPLEX lpCmp = (LPHSFFT_CMPLEX)HeapAlloc(GetProcessHeap() , HEAP_ZERO_MEMORY , UseSamples * sizeof(HSFFT_CMPLEX)) ;
HS_rfft_exec(lpData + start , lpCmp , UseSamples);
//振幅スペクトルを求めながら最大値を求める
double maxdata = 0;
for (int i = 0; i <= UseSamples/2 ; i++)
{
(lpCmp + i)->Real = sqrt(pow((lpCmp + i)->Real , 2) + pow((lpCmp + i)->Imaginary , 2));
if(maxdata < (lpCmp + i)->Real) maxdata = (lpCmp + i)->Real;
}
//最大値で振幅スペクトルを0.0~1.0に正規化する
for (int i = 0; i <= UseSamples/2; i++)
{
(lpCmp + i)->Real /= maxdata;
}
UseSamples /= 2;
UseSamples++;
//表示スペース分にまとめる
int mixdatanums , restdatanums;
double *pData , data;
mixdatanums = UseSamples / (dots - 1) ;
restdatanums = UseSamples % (dots - 1) ;
for (int i = 0; i <= dots; i++)
{
pData = &(lpCmp + i)->Imaginary;
*pData = 0;
for (int j = 0; j < ((i == dots) ? restdatanums : mixdatanums); j++)
{
*pData += (lpCmp + i*mixdatanums + j)->Real;
}
*pData /= mixdatanums;
if(*pData){
*pData = 20 * log10(*pData);
}else{
*pData = -MaxDecibel - 1;
}
}
//描画する
for (int i = startdrawx , pos = 0; i < sizex; i++ , pos++)
{
pData = &(lpCmp + pos)->Imaginary;
if(*pData > -MaxDecibel){
data = (*pData + MaxDecibel) / MaxDecibel;
data *= sizey - 1;
data = sizey - 1 - data;
line_white.SetPosition(i , sizey-1);
line_white.Draw(i , (int)data);
}
}
//カラーテーブルを作る
HDC hdc_color = CreateCompatibleDC(hdc);
HBITMAP hBit_color = CreateCompatibleBitmap(hdc , dots , sizey);
SelectObject(hdc_color , hBit_color);
line.SetDC(hdc_color);
for (int i = 0; i < sizey; i++)
{
line.SetColorS(1.0 - (double)i / (sizey - 1));
line.DrawEx(0,i , dots , i);
}
BitBlt(hdc , startdrawx , 0 , dots , sizey , hdc_color , 0,0 ,SRCAND);
DeleteDC(hdc_color);
DeleteObject(hBit_color);
HeapFree(GetProcessHeap() , NULL , lpCmp);
}else if(Channel == 2){
CHSLine line2(hdc);
line2.SetColor(127,191,255);
//区切り線
line.SetColor(255,255,255);
line.DrawEx(0,sizey/2 , sizex , sizey/2);
wsprintf(string , TEXT("Left"));
SetTextColor(hdc , RGB(255,191,127));
GetTextExtentPoint32(hdc , string , lstrlen(string) , &strSize);
TextOut(hdc , 5 , sizey/4 - strSize.cy/2 , string , lstrlen(string));
wsprintf(string , TEXT("Right"));
SetTextColor(hdc , RGB(127,191,255));
GetTextExtentPoint32(hdc , string , lstrlen(string) , &strSize);
TextOut(hdc , 5 , sizey/2 + sizey/4 - strSize.cy/2 , string , lstrlen(string));
line.DrawEx(10 + strSize.cx , 0 , 10 + strSize.cx , sizey);
line.SetColor(255,191,127);
startdrawx = 10 + strSize.cx + 1;
dots = sizex - startdrawx;
LPHSFFT_CMPLEX lpCmp[2] ;
lpCmp[0] = (LPHSFFT_CMPLEX)HeapAlloc(GetProcessHeap() , HEAP_ZERO_MEMORY , UseSamples * sizeof(HSFFT_CMPLEX)) ;
lpCmp[1] = (LPHSFFT_CMPLEX)HeapAlloc(GetProcessHeap() , HEAP_ZERO_MEMORY , UseSamples * sizeof(HSFFT_CMPLEX)) ;
//FFT実行ブロック
{
double *base[2];
base[0] = (double*)HeapAlloc(GetProcessHeap() , HEAP_ZERO_MEMORY , UseSamples * sizeof(double)) ;
base[1] = (double*)HeapAlloc(GetProcessHeap() , HEAP_ZERO_MEMORY , UseSamples * sizeof(double)) ;
WaveCutChannel(lpData + start * 2 , UseSamples * 2 * sizeof(double) , base[0] , base[1] , 64);
HS_rfft_exec(base[0] , lpCmp[0] , UseSamples);
HS_rfft_exec(base[1] , lpCmp[1] , UseSamples);
HeapFree(GetProcessHeap() , NULL , base[0]);
HeapFree(GetProcessHeap() , NULL , base[1]);
}
UseSamples /= 2;
UseSamples++;
int mixdatanums , restdatanums;
mixdatanums = UseSamples / (dots - 1) ;
restdatanums = UseSamples % (dots - 1) ;
double *pData , data;
for (int h = 0; h < 2; h++)
{
//振幅スペクトルを求めながら最大値を求める
double maxdata = 0;
for (int i = 0; i <= UseSamples ; i++)
{
(lpCmp[h] + i)->Real = sqrt(pow((lpCmp[h] + i)->Real , 2) + pow((lpCmp[h] + i)->Imaginary , 2));
if(maxdata < (lpCmp[h] + i)->Real) maxdata = (lpCmp[h] + i)->Real;
}
//最大値で振幅スペクトルを0.0~1.0に正規化する
for (int i = 0; i <= UseSamples; i++)
{
(lpCmp[h] + i)->Real /= maxdata;
}
//表示スペース分にまとめる
for (int i = 0; i <= dots; i++)
{
pData = &(lpCmp[h] + i)->Imaginary;
*pData = 0;
for (int j = 0; j < ((i == dots) ? restdatanums : mixdatanums); j++)
{
*pData += (lpCmp[h] + i*mixdatanums + j)->Real;
}
*pData /= mixdatanums;
if(*pData){
*pData = 20 * log10(*pData);
}else{
*pData = -MaxDecibel - 1;
}
}
}
//描画する
for (int i = startdrawx , pos = 0; i < sizex; i++ , pos++)
{
pData = &(lpCmp[0] + pos)->Imaginary;
if(*pData > -MaxDecibel){
data = (*pData + MaxDecibel) / MaxDecibel;
data *= sizey/2 - 1;
data = sizey/2 - 1 - data;
line_white.SetPosition(i , sizey/2 - 1);
line_white.Draw(i , (int)data);
}
pData = &(lpCmp[1] + pos)->Imaginary;
if(*pData > -MaxDecibel){
data = (*pData + MaxDecibel) / MaxDecibel;
data *= sizey/2 - 2;
data = sizey - 1 - data;
line_white.SetPosition(i , sizey - 1);
line_white.Draw(i , (int)data);
}
}
//カラーテーブルを作る
HDC hdc_color = CreateCompatibleDC(hdc);
HBITMAP hBit_color = CreateCompatibleBitmap(hdc , dots , sizey/2 - 1);
HDC hdc_color2 = CreateCompatibleDC(hdc);
HBITMAP hBit_color2 = CreateCompatibleBitmap(hdc , dots , sizey/2 - 2);
SelectObject(hdc_color , hBit_color);
SelectObject(hdc_color2 , hBit_color2);
line.SetDC(hdc_color);
line2.SetDC(hdc_color2);
for (int i = 0; i < (sizey/2 - 1); i++)
{
line.SetColorS(1.0 - (double)i / (sizey/2 - 1));
line.DrawEx(0,i , dots , i);
line2.SetColorS(1.0 - (double)i / (sizey/2 - 2));
line2.DrawEx(0,i , dots , i);
}
BitBlt(hdc , startdrawx , 0 , dots , sizey/2 - 1 , hdc_color , 0,0 ,SRCAND);
BitBlt(hdc , startdrawx , sizey/2 + 1 , dots , sizey/2 - 2 , hdc_color2 , 0,0 ,SRCAND);
DeleteDC(hdc_color);
DeleteObject(hBit_color);
DeleteDC(hdc_color2);
DeleteObject(hBit_color2);
HeapFree(GetProcessHeap() , NULL , lpCmp[0]);
HeapFree(GetProcessHeap() , NULL , lpCmp[1]);
}
SelectObject(hdc , hOldFont);
DeleteObject(hFont);
}
void WPV_SpectrumBar(HDC hdc, int sizex, int sizey, LPWaveFileBaseHeader lpHeader, double *lpData, int pos){
if(!lpHeader || !lpData)return;
int Channel = lpHeader->Fmt.tagPCMWaveFormat.wf.nChannels;
lpData += lpHeader->Fmt.tagPCMWaveFormat.wf.nSamplesPerSec * Channel;
lpData += pos * Channel;
HFONT hFont , hOldFont;
HPEN hOldPen = (HPEN)SelectObject(hdc , GetStockObject(DC_PEN));
HBRUSH hOldBrush = (HBRUSH)SelectObject(hdc , GetStockObject(DC_BRUSH));
TCHAR string[32];
SIZE strSize;
if(!hdc)return;
hFont = MyFont(TEXT("メイリオ") , 48 , 0 , 0);
hOldFont = (HFONT)SelectObject(hdc , hFont);
CHSLine line(hdc);
SetBkMode(hdc ,TRANSPARENT);
int UseSamples = 8192;
int start , end;
int startdrawx , dots;
int barnums = 160;
int paddingx ;
if(UseSamples%2)UseSamples++;
start = -UseSamples/2;
end = UseSamples/2 - 1;
if(Channel == 1){
wsprintf(string , TEXT("Mono"));
SetTextColor(hdc , RGB(191,255,127));
GetTextExtentPoint32(hdc , string , lstrlen(string) , &strSize);
TextOut(hdc , 5 , sizey/2 - strSize.cy/2 , string , lstrlen(string));
line.SetColor(191,255,127);
line.DrawEx(10 + strSize.cx , 0 , 10 + strSize.cx , sizey);
startdrawx = 10 + strSize.cx + 1;
dots = sizex - startdrawx;
paddingx = (dots + 1) - (dots / barnums) * barnums;
paddingx /= 2;
LPHSFFT_CMPLEX lpCmp = (LPHSFFT_CMPLEX)HeapAlloc(GetProcessHeap() , HEAP_ZERO_MEMORY , UseSamples * sizeof(HSFFT_CMPLEX)) ;
HS_rfft_exec(lpData + start , lpCmp , UseSamples);
//振幅スペクトルを求めながら最大値を求める
double maxdata = 0;
for (int i = 0; i <= UseSamples/2 ; i++)
{
(lpCmp + i)->Real = sqrt(pow((lpCmp + i)->Real , 2) + pow((lpCmp + i)->Imaginary , 2));
if(maxdata < (lpCmp + i)->Real) maxdata = (lpCmp + i)->Real;
}
//最大値で振幅スペクトルを0.0~1.0に正規化する
for (int i = 0; i <= UseSamples/2; i++)
{
(lpCmp + i)->Real /= maxdata;
}
UseSamples /= 2;
UseSamples++;
//表示スペース分にまとめる
int mixdatanums , restdatanums;
double *pData , data;
mixdatanums = UseSamples / (barnums - 1) ;
restdatanums = UseSamples % (barnums - 1) ;
for (int i = 0; i < (barnums); i++)
{
pData = &(lpCmp + i)->Imaginary;
*pData = 0;
for (int j = 0; j < ((i == dots) ? restdatanums : mixdatanums); j++)
{
*pData += (lpCmp + i*mixdatanums + j)->Real;
}
*pData /= mixdatanums;
if(*pData){
*pData = 20 * log10(*pData);
}else{
*pData = -MaxDecibel - 1;
}
}
SetDCPenColor(hdc , line.GetColor());
SetDCBrushColor(hdc , line.GetColor());
//描画する
for (int i = startdrawx , pos = 0; pos < barnums; i+= dots / barnums, pos++)
{
pData = &(lpCmp + pos)->Imaginary;
if(*pData > -MaxDecibel){
data = (*pData + MaxDecibel) / MaxDecibel;
data *= sizey - 1;
data = sizey - 1 - data;
Rectangle(hdc , i + 1 , (int)data , i + dots / barnums , sizey);
}
}
HeapFree(GetProcessHeap() , NULL , lpCmp);
}else if(Channel == 2){
CHSLine line2(hdc);
line2.SetColor(127,191,255);
//区切り線
line.SetColor(255,255,255);
line.DrawEx(0,sizey/2 , sizex , sizey/2);
wsprintf(string , TEXT("Left"));
SetTextColor(hdc , RGB(255,191,127));
GetTextExtentPoint32(hdc , string , lstrlen(string) , &strSize);
TextOut(hdc , 5 , sizey/4 - strSize.cy/2 , string , lstrlen(string));
wsprintf(string , TEXT("Right"));
SetTextColor(hdc , RGB(127,191,255));
GetTextExtentPoint32(hdc , string , lstrlen(string) , &strSize);
TextOut(hdc , 5 , sizey/2 + sizey/4 - strSize.cy/2 , string , lstrlen(string));
line.DrawEx(10 + strSize.cx , 0 , 10 + strSize.cx , sizey);
line.SetColor(255,191,127);
startdrawx = 10 + strSize.cx + 1;
dots = sizex - startdrawx;
paddingx = (dots + 1) - (dots / barnums) * barnums;
paddingx /= 2;
LPHSFFT_CMPLEX lpCmp[2] ;
lpCmp[0] = (LPHSFFT_CMPLEX)HeapAlloc(GetProcessHeap() , HEAP_ZERO_MEMORY , UseSamples * sizeof(HSFFT_CMPLEX)) ;
lpCmp[1] = (LPHSFFT_CMPLEX)HeapAlloc(GetProcessHeap() , HEAP_ZERO_MEMORY , UseSamples * sizeof(HSFFT_CMPLEX)) ;
//FFT実行ブロック
{
double *base[2];
base[0] = (double*)HeapAlloc(GetProcessHeap() , HEAP_ZERO_MEMORY , UseSamples * sizeof(double)) ;
base[1] = (double*)HeapAlloc(GetProcessHeap() , HEAP_ZERO_MEMORY , UseSamples * sizeof(double)) ;
WaveCutChannel(lpData + start * 2 , UseSamples * 2 * sizeof(double) , base[0] , base[1] , 64);
HS_rfft_exec(base[0] , lpCmp[0] , UseSamples);
HS_rfft_exec(base[1] , lpCmp[1] , UseSamples);
HeapFree(GetProcessHeap() , NULL , base[0]);
HeapFree(GetProcessHeap() , NULL , base[1]);
}
UseSamples /= 2;
UseSamples++;
int mixdatanums , restdatanums;
mixdatanums = UseSamples / (barnums - 1) ;
restdatanums = UseSamples % (barnums - 1) ;
double *pData , data;
for (int h = 0; h < 2; h++)
{
//振幅スペクトルを求めながら最大値を求める
double maxdata = 0;
for (int i = 0; i <= UseSamples ; i++)
{
(lpCmp[h] + i)->Real = sqrt(pow((lpCmp[h] + i)->Real , 2) + pow((lpCmp[h] + i)->Imaginary , 2));
if(maxdata < (lpCmp[h] + i)->Real) maxdata = (lpCmp[h] + i)->Real;
}
//最大値で振幅スペクトルを0.0~1.0に正規化する
for (int i = 0; i <= UseSamples; i++)
{
(lpCmp[h] + i)->Real /= maxdata;
}
//表示スペース分にまとめる
for (int i = 0; i < barnums; i++)
{
pData = &(lpCmp[h] + i)->Imaginary;
*pData = 0;
for (int j = 0; j < ((i == dots) ? restdatanums : mixdatanums); j++)
{
*pData += (lpCmp[h] + i*mixdatanums + j)->Real;
}
*pData /= mixdatanums;
if(*pData){
*pData = 20 * log10(*pData);
}else{
*pData = -MaxDecibel - 1;
}
}
}
//描画する
for (int i = startdrawx , pos = 0; pos < barnums; i+=dots / barnums , pos++)
{
SetDCPenColor(hdc , line.GetColor());
SetDCBrushColor(hdc , line.GetColor());
pData = &(lpCmp[0] + pos)->Imaginary;
if(*pData > -MaxDecibel){
data = (*pData + MaxDecibel) / MaxDecibel;
data *= sizey/2 - 1;
data = sizey/2 - 1 - data;
Rectangle(hdc , i + 1 , (int)data , i + dots / barnums , sizey/2);
}
SetDCPenColor(hdc , line2.GetColor());
SetDCBrushColor(hdc , line2.GetColor());
pData = &(lpCmp[1] + pos)->Imaginary;
if(*pData > -MaxDecibel){
data = (*pData + MaxDecibel) / MaxDecibel;
data *= sizey/2 - 2;
data = sizey - 1 - data;
Rectangle(hdc , i + 1 , (int)data , i + dots / barnums , sizey);
}
}
HeapFree(GetProcessHeap() , NULL , lpCmp[0]);
HeapFree(GetProcessHeap() , NULL , lpCmp[1]);
}
SelectObject(hdc , hOldPen);
SelectObject(hdc , hOldBrush);
SelectObject(hdc , hOldFont);
DeleteObject(hFont);
}
void WPV_SpectrumBar2(HDC hdc, int sizex, int sizey, LPWaveFileBaseHeader lpHeader, double *lpData, int pos){
if(!lpHeader || !lpData)return;
int Channel = lpHeader->Fmt.tagPCMWaveFormat.wf.nChannels;
lpData += lpHeader->Fmt.tagPCMWaveFormat.wf.nSamplesPerSec * Channel;
lpData += pos * Channel;
HFONT hFont , hOldFont;
HPEN hOldPen = (HPEN)SelectObject(hdc , GetStockObject(DC_PEN));
HBRUSH hOldBrush = (HBRUSH)SelectObject(hdc , GetStockObject(DC_BRUSH));
TCHAR string[32];
SIZE strSize;
if(!hdc)return;
hFont = MyFont(TEXT("メイリオ") , 48 , 0 , 0);
hOldFont = (HFONT)SelectObject(hdc , hFont);
CHSLine line(hdc);
SetBkMode(hdc ,TRANSPARENT);
int UseSamples = 8192;
int start , end;
int startdrawx , dots;
int barnums = 160;
int paddingx;
if(UseSamples%2)UseSamples++;
start = -UseSamples/2;
end = UseSamples/2 - 1;
SetDCPenColor(hdc , RGB(255,255,255));
SetDCBrushColor(hdc , RGB(255,255,255));
if(Channel == 1){
wsprintf(string , TEXT("Mono"));
SetTextColor(hdc , RGB(191,255,127));
GetTextExtentPoint32(hdc , string , lstrlen(string) , &strSize);
TextOut(hdc , 5 , sizey/2 - strSize.cy/2 , string , lstrlen(string));
line.SetColor(191,255,127);
line.DrawEx(10 + strSize.cx , 0 , 10 + strSize.cx , sizey);
startdrawx = 10 + strSize.cx + 1;
dots = sizex - startdrawx;
paddingx = (dots + 1) - (dots / barnums) * barnums;
paddingx /= 2;
LPHSFFT_CMPLEX lpCmp = (LPHSFFT_CMPLEX)HeapAlloc(GetProcessHeap() , HEAP_ZERO_MEMORY , UseSamples * sizeof(HSFFT_CMPLEX)) ;
HS_rfft_exec(lpData + start , lpCmp , UseSamples);
//振幅スペクトルを求めながら最大値を求める
double maxdata = 0;
for (int i = 0; i <= UseSamples/2 ; i++)
{
(lpCmp + i)->Real = sqrt(pow((lpCmp + i)->Real , 2) + pow((lpCmp + i)->Imaginary , 2));
if(maxdata < (lpCmp + i)->Real) maxdata = (lpCmp + i)->Real;
}
//最大値で振幅スペクトルを0.0~1.0に正規化する
for (int i = 0; i <= UseSamples/2; i++)
{
(lpCmp + i)->Real /= maxdata;
}
UseSamples /= 2;
UseSamples++;
//表示スペース分にまとめる
int mixdatanums , restdatanums;
double *pData , data;
mixdatanums = UseSamples / (barnums - 1) ;
restdatanums = UseSamples % (barnums - 1) ;
for (int i = 0; i < (barnums); i++)
{
pData = &(lpCmp + i)->Imaginary;
*pData = 0;
for (int j = 0; j < ((i == dots) ? restdatanums : mixdatanums); j++)
{
*pData += (lpCmp + i*mixdatanums + j)->Real;
}
*pData /= mixdatanums;
if(*pData){
*pData = 20 * log10(*pData);
}else{
*pData = -MaxDecibel - 1;
}
}
//描画する
for (int i = startdrawx , pos = 0; pos < barnums; i+= dots / barnums, pos++)
{
pData = &(lpCmp + pos)->Imaginary;
if(*pData > -MaxDecibel){
data = (*pData + MaxDecibel) / MaxDecibel;
data *= sizey - 1;
data = sizey - 1 - data;
Rectangle(hdc , i + 1 , (int)data , i + dots / barnums , sizey);
}
}
//カラーテーブルを作る
HDC hdc_color = CreateCompatibleDC(hdc);
HBITMAP hBit_color = CreateCompatibleBitmap(hdc , dots , sizey);
SelectObject(hdc_color , hBit_color);
line.SetDC(hdc_color);
for (int i = 0; i < sizey; i++)
{
line.SetColorS(1.0 - (double)i / (sizey - 1));
line.DrawEx(0,i , dots , i);
}
BitBlt(hdc , startdrawx , 0 , dots , sizey , hdc_color , 0,0 ,SRCAND);
DeleteDC(hdc_color);
DeleteObject(hBit_color);
HeapFree(GetProcessHeap() , NULL , lpCmp);
}else if(Channel == 2){
CHSLine line2(hdc);
line2.SetColor(127,191,255);
//区切り線
line.SetColor(255,255,255);
line.DrawEx(0,sizey/2 , sizex , sizey/2);
wsprintf(string , TEXT("Left"));
SetTextColor(hdc , RGB(255,191,127));
GetTextExtentPoint32(hdc , string , lstrlen(string) , &strSize);
TextOut(hdc , 5 , sizey/4 - strSize.cy/2 , string , lstrlen(string));
wsprintf(string , TEXT("Right"));
SetTextColor(hdc , RGB(127,191,255));
GetTextExtentPoint32(hdc , string , lstrlen(string) , &strSize);
TextOut(hdc , 5 , sizey/2 + sizey/4 - strSize.cy/2 , string , lstrlen(string));
line.DrawEx(10 + strSize.cx , 0 , 10 + strSize.cx , sizey);
line.SetColor(255,191,127);
startdrawx = 10 + strSize.cx + 1;
dots = sizex - startdrawx;
paddingx = (dots + 1) - (dots / barnums) * barnums;
paddingx /= 2;
LPHSFFT_CMPLEX lpCmp[2] ;
lpCmp[0] = (LPHSFFT_CMPLEX)HeapAlloc(GetProcessHeap() , HEAP_ZERO_MEMORY , UseSamples * sizeof(HSFFT_CMPLEX)) ;
lpCmp[1] = (LPHSFFT_CMPLEX)HeapAlloc(GetProcessHeap() , HEAP_ZERO_MEMORY , UseSamples * sizeof(HSFFT_CMPLEX)) ;
//FFT実行ブロック
{
double *base[2];
base[0] = (double*)HeapAlloc(GetProcessHeap() , HEAP_ZERO_MEMORY , UseSamples * sizeof(double)) ;
base[1] = (double*)HeapAlloc(GetProcessHeap() , HEAP_ZERO_MEMORY , UseSamples * sizeof(double)) ;
WaveCutChannel(lpData + start * 2 , UseSamples * 2 * sizeof(double) , base[0] , base[1] , 64);
HS_rfft_exec(base[0] , lpCmp[0] , UseSamples);
HS_rfft_exec(base[1] , lpCmp[1] , UseSamples);
HeapFree(GetProcessHeap() , NULL , base[0]);
HeapFree(GetProcessHeap() , NULL , base[1]);
}
UseSamples /= 2;
UseSamples++;
int mixdatanums , restdatanums;
mixdatanums = UseSamples / (barnums - 1) ;
restdatanums = UseSamples % (barnums - 1) ;
double *pData , data;
for (int h = 0; h < 2; h++)
{
//振幅スペクトルを求めながら最大値を求める
double maxdata = 0;
for (int i = 0; i <= UseSamples ; i++)
{
(lpCmp[h] + i)->Real = sqrt(pow((lpCmp[h] + i)->Real , 2) + pow((lpCmp[h] + i)->Imaginary , 2));
if(maxdata < (lpCmp[h] + i)->Real) maxdata = (lpCmp[h] + i)->Real;
}
//最大値で振幅スペクトルを0.0~1.0に正規化する
for (int i = 0; i <= UseSamples; i++)
{
(lpCmp[h] + i)->Real /= maxdata;
}
//表示スペース分にまとめる
for (int i = 0; i < barnums; i++)
{
pData = &(lpCmp[h] + i)->Imaginary;
*pData = 0;
for (int j = 0; j < ((i == dots) ? restdatanums : mixdatanums); j++)
{
*pData += (lpCmp[h] + i*mixdatanums + j)->Real;
}
*pData /= mixdatanums;
if(*pData){
*pData = 20 * log10(*pData);
}else{
*pData = -MaxDecibel - 1;
}
}
}
//描画する
for (int i = startdrawx , pos = 0; pos < barnums; i+=dots / barnums , pos++)
{
pData = &(lpCmp[0] + pos)->Imaginary;
if(*pData > -MaxDecibel){
data = (*pData + MaxDecibel) / MaxDecibel;
data *= sizey/2 - 1;
data = sizey/2 - 1 - data;
Rectangle(hdc , i + 1 , (int)data , i + dots / barnums , sizey/2);
}
pData = &(lpCmp[1] + pos)->Imaginary;
if(*pData > -MaxDecibel){
data = (*pData + MaxDecibel) / MaxDecibel;
data *= sizey/2 - 2;
data = sizey - 1 - data;
Rectangle(hdc , i + 1 , (int)data , i + dots / barnums , sizey);
}
}
//カラーテーブルを作る
HDC hdc_color = CreateCompatibleDC(hdc);
HBITMAP hBit_color = CreateCompatibleBitmap(hdc , dots , sizey/2 - 1);
HDC hdc_color2 = CreateCompatibleDC(hdc);
HBITMAP hBit_color2 = CreateCompatibleBitmap(hdc , dots , sizey/2 - 2);
SelectObject(hdc_color , hBit_color);
SelectObject(hdc_color2 , hBit_color2);
line.SetDC(hdc_color);
line2.SetDC(hdc_color2);
for (int i = 0; i < (sizey/2 - 1); i++)
{
line.SetColorS(1.0 - (double)i / (sizey/2 - 1));
line.DrawEx(0,i , dots , i);
line2.SetColorS(1.0 - (double)i / (sizey/2 - 2));
line2.DrawEx(0,i , dots , i);
}
BitBlt(hdc , startdrawx , 0 , dots , sizey/2 - 1 , hdc_color , 0,0 ,SRCAND);
BitBlt(hdc , startdrawx , sizey/2 + 1 , dots , sizey/2 - 2 , hdc_color2 , 0,0 ,SRCAND);
DeleteDC(hdc_color);
DeleteObject(hBit_color);
DeleteDC(hdc_color2);
DeleteObject(hBit_color2);
HeapFree(GetProcessHeap() , NULL , lpCmp[0]);
HeapFree(GetProcessHeap() , NULL , lpCmp[1]);
}
SelectObject(hdc , hOldPen);
SelectObject(hdc , hOldBrush);
SelectObject(hdc , hOldFont);
DeleteObject(hFont);
}
void WPV_SpectrumMeter(HDC hdc, int sizex, int sizey, LPWaveFileBaseHeader lpHeader, double *lpData, int pos){
if(!lpHeader || !lpData)return;
int Channel = lpHeader->Fmt.tagPCMWaveFormat.wf.nChannels;
lpData += lpHeader->Fmt.tagPCMWaveFormat.wf.nSamplesPerSec * Channel;
lpData += pos * Channel;
HFONT hFont , hOldFont;
TCHAR string[32];
SIZE strSize;
if(!hdc)return;
hFont = MyFont(TEXT("メイリオ") , 48 , 0 , 0);
hOldFont = (HFONT)SelectObject(hdc , hFont);
CHSLine line(hdc);
SetBkMode(hdc ,TRANSPARENT);
int UseSamples = 8192;
int start , end;
int startdrawx , dots;
if(UseSamples%2)UseSamples++;
start = -UseSamples/2;
end = UseSamples/2 - 1;
if(Channel == 1){
wsprintf(string , TEXT("Mono"));
SetTextColor(hdc , RGB(191,255,127));
GetTextExtentPoint32(hdc , string , lstrlen(string) , &strSize);
TextOut(hdc , 5 , sizey/2 - strSize.cy/2 , string , lstrlen(string));
line.SetColor(191,255,127);
line.DrawEx(10 + strSize.cx , 0 , 10 + strSize.cx , sizey);
startdrawx = 10 + strSize.cx + 6;
dots = sizex - startdrawx - 5;
LPHSFFT_CMPLEX lpCmp = (LPHSFFT_CMPLEX)HeapAlloc(GetProcessHeap() , HEAP_ZERO_MEMORY , UseSamples * sizeof(HSFFT_CMPLEX)) ;
HS_rfft_exec(lpData + start , lpCmp , UseSamples);
//振幅スペクトルを求めながら最大値を求める
double maxdata = 0;
for (int i = 0; i <= UseSamples/2 ; i++)
{
(lpCmp + i)->Real = sqrt(pow((lpCmp + i)->Real , 2) + pow((lpCmp + i)->Imaginary , 2));
if(maxdata < (lpCmp + i)->Real) maxdata = (lpCmp + i)->Real;
}
//最大値で振幅スペクトルを0.0~1.0に正規化する
for (int i = 0; i <= UseSamples/2; i++)
{
(lpCmp + i)->Real /= maxdata;
}
UseSamples /= 2;
UseSamples++;
//表示スペース分にまとめる
int mixdatanums , restdatanums;
double *pData , data;
mixdatanums = UseSamples / (dots - 1) ;
restdatanums = UseSamples % (dots - 1) ;
for (int i = 0; i <= dots; i++)
{
pData = &(lpCmp + i)->Imaginary;
*pData = 0;
for (int j = 0; j < ((i == dots) ? restdatanums : mixdatanums); j++)
{
*pData += (lpCmp + i*mixdatanums + j)->Real;
}
*pData /= mixdatanums;
if(*pData){
*pData = 20 * log10(*pData);
}else{
*pData = -MaxDecibel - 1;
}
}
//描画する
double s = 1, v = 1;
s = 0.75;
for (int i = startdrawx , pos = 0; pos < dots; i++ , pos++)
{
pData = &(lpCmp + pos)->Imaginary;
if(*pData > -MaxDecibel){
data = (*pData + MaxDecibel) / MaxDecibel;
line.SetColorHSV(120 - data*120 , s , v);
line.DrawEx( i , 10 , i , sizey - 11);
/*
if(i == startdrawx)line.SetPosition(i , (int)data);
else line.Draw(i , (int)data);
*/
}else {
line.SetColorHSV(120 , s , v);
line.DrawEx( i , 10 , i , sizey - 11);
/*
if(i == startdrawx) line.SetPosition(i , sizey - 1);
else line.Draw(i , sizey - 1);
*/
}
}
HeapFree(GetProcessHeap() , NULL , lpCmp);
}else if(Channel == 2){
CHSLine line2(hdc);
line2.SetColor(127,191,255);
//区切り線
line.SetColor(255,255,255);
line.DrawEx(0,sizey/2 , sizex , sizey/2);
wsprintf(string , TEXT("Left"));
SetTextColor(hdc , RGB(255,191,127));
GetTextExtentPoint32(hdc , string , lstrlen(string) , &strSize);
TextOut(hdc , 5 , sizey/4 - strSize.cy/2 , string , lstrlen(string));
wsprintf(string , TEXT("Right"));
SetTextColor(hdc , RGB(127,191,255));
GetTextExtentPoint32(hdc , string , lstrlen(string) , &strSize);
TextOut(hdc , 5 , sizey/2 + sizey/4 - strSize.cy/2 , string , lstrlen(string));
line.DrawEx(10 + strSize.cx , 0 , 10 + strSize.cx , sizey);
line.SetColor(255,191,127);
startdrawx = 10 + strSize.cx + 6;
dots = sizex - startdrawx - 5;
LPHSFFT_CMPLEX lpCmp[2] ;
lpCmp[0] = (LPHSFFT_CMPLEX)HeapAlloc(GetProcessHeap() , HEAP_ZERO_MEMORY , UseSamples * sizeof(HSFFT_CMPLEX)) ;
lpCmp[1] = (LPHSFFT_CMPLEX)HeapAlloc(GetProcessHeap() , HEAP_ZERO_MEMORY , UseSamples * sizeof(HSFFT_CMPLEX)) ;
//FFT実行ブロック
{
double *base[2];
base[0] = (double*)HeapAlloc(GetProcessHeap() , HEAP_ZERO_MEMORY , UseSamples * sizeof(double)) ;
base[1] = (double*)HeapAlloc(GetProcessHeap() , HEAP_ZERO_MEMORY , UseSamples * sizeof(double)) ;
WaveCutChannel(lpData + start * 2 , UseSamples * 2 * sizeof(double) , base[0] , base[1] , 64);
HS_rfft_exec(base[0] , lpCmp[0] , UseSamples);
HS_rfft_exec(base[1] , lpCmp[1] , UseSamples);
HeapFree(GetProcessHeap() , NULL , base[0]);
HeapFree(GetProcessHeap() , NULL , base[1]);
}
UseSamples /= 2;
UseSamples++;
int mixdatanums , restdatanums;
mixdatanums = UseSamples / (dots - 1) ;
restdatanums = UseSamples % (dots - 1) ;
double *pData , data;
for (int h = 0; h < 2; h++)
{
//振幅スペクトルを求めながら最大値を求める
double maxdata = 0;
for (int i = 0; i <= UseSamples ; i++)
{
(lpCmp[h] + i)->Real = sqrt(pow((lpCmp[h] + i)->Real , 2) + pow((lpCmp[h] + i)->Imaginary , 2));
if(maxdata < (lpCmp[h] + i)->Real) maxdata = (lpCmp[h] + i)->Real;
}
//最大値で振幅スペクトルを0.0~1.0に正規化する
for (int i = 0; i <= UseSamples; i++)
{
(lpCmp[h] + i)->Real /= maxdata;
}
//表示スペース分にまとめる
for (int i = 0; i <= dots; i++)
{
pData = &(lpCmp[h] + i)->Imaginary;
*pData = 0;
for (int j = 0; j < ((i == dots) ? restdatanums : mixdatanums); j++)
{
*pData += (lpCmp[h] + i*mixdatanums + j)->Real;
}
*pData /= mixdatanums;
if(*pData){
*pData = 20 * log10(*pData);
}else{
*pData = -MaxDecibel - 1;
}
}
}
double s = 1, v = 1;
s = 0.75;
//描画する
for (int i = startdrawx , pos = 0; pos < dots; i++ , pos++)
{
pData = &(lpCmp[0] + pos)->Imaginary;
if(*pData > -MaxDecibel){
data = (*pData + MaxDecibel) / MaxDecibel;
line.SetColorHSV(120 - data*120 , s , v);
line.DrawEx( i , 10 , i , sizey/2 - 11);
}else{
line.SetColorHSV(120 , s , v);
line.DrawEx( i , 10 , i , sizey/2 - 11);
}
pData = &(lpCmp[1] + pos)->Imaginary;
if(*pData > -MaxDecibel){
data = (*pData + MaxDecibel) / MaxDecibel;
line.SetColorHSV(120 - data*120 , s , v);
line.DrawEx( i , sizey/2 + 11 , i , sizey - 11);
}else{
line.SetColorHSV(120 , s , v);
line.DrawEx( i , sizey/2 + 11 , i , sizey - 11);
}
}
HeapFree(GetProcessHeap() , NULL , lpCmp[0]);
HeapFree(GetProcessHeap() , NULL , lpCmp[1]);
}
SelectObject(hdc , hOldFont);
DeleteObject(hFont);
}
void WPV_SpectrumMeter2(HDC hdc, int sizex, int sizey, LPWaveFileBaseHeader lpHeader, double *lpData, int pos){
if(!lpHeader || !lpData)return;
int Channel = lpHeader->Fmt.tagPCMWaveFormat.wf.nChannels;
lpData += lpHeader->Fmt.tagPCMWaveFormat.wf.nSamplesPerSec * Channel;
lpData += pos * Channel;
HFONT hFont , hOldFont;
TCHAR string[32];
SIZE strSize;
if(!hdc)return;
hFont = MyFont(TEXT("メイリオ") , 48 , 0 , 0);
hOldFont = (HFONT)SelectObject(hdc , hFont);
CHSLine line(hdc);
SetBkMode(hdc ,TRANSPARENT);
int UseSamples = 8192;
int start , end;
int startdrawx , dots;
if(UseSamples%2)UseSamples++;
start = -UseSamples/2;
end = UseSamples/2 - 1;
if(Channel == 1){
wsprintf(string , TEXT("Mono"));
SetTextColor(hdc , RGB(191,255,127));
GetTextExtentPoint32(hdc , string , lstrlen(string) , &strSize);
TextOut(hdc , 5 , sizey/2 - strSize.cy/2 , string , lstrlen(string));
line.SetColor(191,255,127);
line.DrawEx(10 + strSize.cx , 0 , 10 + strSize.cx , sizey);
startdrawx = 10 + strSize.cx + 6;
dots = sizex - startdrawx - 5;
LPHSFFT_CMPLEX lpCmp = (LPHSFFT_CMPLEX)HeapAlloc(GetProcessHeap() , HEAP_ZERO_MEMORY , UseSamples * sizeof(HSFFT_CMPLEX)) ;
HS_rfft_exec(lpData + start , lpCmp , UseSamples);
//振幅スペクトルを求めながら最大値を求める
double maxdata = 0;
for (int i = 0; i <= UseSamples/2 ; i++)
{
(lpCmp + i)->Real = sqrt(pow((lpCmp + i)->Real , 2) + pow((lpCmp + i)->Imaginary , 2));
if(maxdata < (lpCmp + i)->Real) maxdata = (lpCmp + i)->Real;
}
//最大値で振幅スペクトルを0.0~1.0に正規化する
for (int i = 0; i <= UseSamples/2; i++)
{
(lpCmp + i)->Real /= maxdata;
}
UseSamples /= 2;
UseSamples++;
//表示スペース分にまとめる
int mixdatanums , restdatanums;
double *pData , data;
mixdatanums = UseSamples / (dots - 1) ;
restdatanums = UseSamples % (dots - 1) ;
for (int i = 0; i <= dots; i++)
{
pData = &(lpCmp + i)->Imaginary;
*pData = 0;
for (int j = 0; j < ((i == dots) ? restdatanums : mixdatanums); j++)
{
*pData += (lpCmp + i*mixdatanums + j)->Real;
}
*pData /= mixdatanums;
if(*pData){
*pData = 20 * log10(*pData);
}else{
*pData = -MaxDecibel - 1;
}
}
//描画する
double h = line.GetColorH() , s = 1, v = 1;
for (int i = startdrawx , pos = 0; pos < dots; i++ , pos++)
{
pData = &(lpCmp + pos)->Imaginary;
if(*pData > -MaxDecibel){
data = (*pData + MaxDecibel) / MaxDecibel;
line.SetColorHSV(h , data , v);
line.DrawEx( i , 10 , i , sizey - 11);
/*
if(i == startdrawx)line.SetPosition(i , (int)data);
else line.Draw(i , (int)data);
*/
}else {
line.SetColorHSV(h , data , v);
line.DrawEx( i , 10 , i , sizey - 11);
/*
if(i == startdrawx) line.SetPosition(i , sizey - 1);
else line.Draw(i , sizey - 1);
*/
}
}
HeapFree(GetProcessHeap() , NULL , lpCmp);
}else if(Channel == 2){
CHSLine line2(hdc);
line2.SetColor(127,191,255);
//区切り線
line.SetColor(255,255,255);
line.DrawEx(0,sizey/2 , sizex , sizey/2);
wsprintf(string , TEXT("Left"));
SetTextColor(hdc , RGB(255,191,127));
GetTextExtentPoint32(hdc , string , lstrlen(string) , &strSize);
TextOut(hdc , 5 , sizey/4 - strSize.cy/2 , string , lstrlen(string));
wsprintf(string , TEXT("Right"));
SetTextColor(hdc , RGB(127,191,255));
GetTextExtentPoint32(hdc , string , lstrlen(string) , &strSize);
TextOut(hdc , 5 , sizey/2 + sizey/4 - strSize.cy/2 , string , lstrlen(string));
line.DrawEx(10 + strSize.cx , 0 , 10 + strSize.cx , sizey);
line.SetColor(255,191,127);
startdrawx = 10 + strSize.cx + 6;
dots = sizex - startdrawx - 5;
LPHSFFT_CMPLEX lpCmp[2] ;
lpCmp[0] = (LPHSFFT_CMPLEX)HeapAlloc(GetProcessHeap() , HEAP_ZERO_MEMORY , UseSamples * sizeof(HSFFT_CMPLEX)) ;
lpCmp[1] = (LPHSFFT_CMPLEX)HeapAlloc(GetProcessHeap() , HEAP_ZERO_MEMORY , UseSamples * sizeof(HSFFT_CMPLEX)) ;
//FFT実行ブロック
{
double *base[2];
base[0] = (double*)HeapAlloc(GetProcessHeap() , HEAP_ZERO_MEMORY , UseSamples * sizeof(double)) ;
base[1] = (double*)HeapAlloc(GetProcessHeap() , HEAP_ZERO_MEMORY , UseSamples * sizeof(double)) ;
WaveCutChannel(lpData + start * 2 , UseSamples * 2 * sizeof(double) , base[0] , base[1] , 64);
HS_rfft_exec(base[0] , lpCmp[0] , UseSamples);
HS_rfft_exec(base[1] , lpCmp[1] , UseSamples);
HeapFree(GetProcessHeap() , NULL , base[0]);
HeapFree(GetProcessHeap() , NULL , base[1]);
}
UseSamples /= 2;
UseSamples++;
int mixdatanums , restdatanums;
mixdatanums = UseSamples / (dots - 1) ;
restdatanums = UseSamples % (dots - 1) ;
double *pData , data;
for (int h = 0; h < 2; h++)
{
//振幅スペクトルを求めながら最大値を求める
double maxdata = 0;
for (int i = 0; i <= UseSamples ; i++)
{
(lpCmp[h] + i)->Real = sqrt(pow((lpCmp[h] + i)->Real , 2) + pow((lpCmp[h] + i)->Imaginary , 2));
if(maxdata < (lpCmp[h] + i)->Real) maxdata = (lpCmp[h] + i)->Real;
}
//最大値で振幅スペクトルを0.0~1.0に正規化する
for (int i = 0; i <= UseSamples; i++)
{
(lpCmp[h] + i)->Real /= maxdata;
}
//表示スペース分にまとめる
for (int i = 0; i <= dots; i++)
{
pData = &(lpCmp[h] + i)->Imaginary;
*pData = 0;
for (int j = 0; j < ((i == dots) ? restdatanums : mixdatanums); j++)
{
*pData += (lpCmp[h] + i*mixdatanums + j)->Real;
}
*pData /= mixdatanums;
if(*pData){
*pData = 20 * log10(*pData);
}else{
*pData = -MaxDecibel - 1;
}
}
}
double h = line.GetColorH() , h2 = line2.GetColorH() , s = 1, v = 1;
//描画する
for (int i = startdrawx , pos = 0; pos < dots; i++ , pos++)
{
pData = &(lpCmp[0] + pos)->Imaginary;
if(*pData > -MaxDecibel){
data = (*pData + MaxDecibel) / MaxDecibel;
line.SetColorHSV(h , data , v);
line.DrawEx( i , 10 , i , sizey/2 - 11);
}else{
line.SetColorHSV(h , 0 , v);
line.DrawEx( i , 10 , i , sizey/2 - 11);
}
pData = &(lpCmp[1] + pos)->Imaginary;
if(*pData > -MaxDecibel){
data = (*pData + MaxDecibel) / MaxDecibel;
line.SetColorHSV(h2 , data , v);
line.DrawEx( i , sizey/2 + 11 , i , sizey - 11);
}else{
line.SetColorHSV(h2 , 0 , v);
line.DrawEx( i , sizey/2 + 11 , i , sizey - 11);
}
}
HeapFree(GetProcessHeap() , NULL , lpCmp[0]);
HeapFree(GetProcessHeap() , NULL , lpCmp[1]);
}
SelectObject(hdc , hOldFont);
DeleteObject(hFont);
}
/*-------------------------------------------------------------------------------------*/
/*--------------------------------------[EOF]------------------------------------------*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment