🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

1回答

2015閲覧

ヒープ破壊が起きてしまう【音声入力】

YMD_kts

総合スコア23

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

1クリップ

投稿2019/11/06 08:29

こちらの質問を行った者です。
回答を参考に16bitの波形データに合わせるようにBYTE型でなくint16_t型を使用するようにしました。
しかし下記コードのヒープ破壊エラー部のreallocにてヒープ破壊が起きてしまいます。
dwBytesRecirdedに問題があるのかと睨んでいるのですが...
また、その下のfor文でエラーを出す時もありなぜこうなるのかイマイチよくわかりません

参考サイト
音声の入力
マイクからリアルタイムで音声を取得する(C++)

case MM_WIM_DATA: bTmp = (int16_t*)realloc(bSave, dwLength + ((PWAVEHDR)lp)->dwBytesRecorded);    //ヒープ破壊エラー部 if (blReset || !bTmp) { waveInClose(hWaveIn); blReset = FALSE; return 0; } bSave = bTmp; for (dwCount = 0; dwCount < ((PWAVEHDR)lp)->dwBytesRecorded; dwCount++) * (bSave + dwLength + dwCount) = *(((PWAVEHDR)lp)->lpData + dwCount); dwLength += ((PWAVEHDR)lp)->dwBytesRecorded; waveInAddBuffer(hWaveIn, (PWAVEHDR)lp, sizeof(WAVEHDR)); //FFT処理 fft1((double*)((PWAVEHDR)lp)->lpData, zeroData, (int)((LPWAVEHDR)lp)->dwBytesRecorded, 0, 0); return 0;

コード全文は下に記載

C++

1#include <windows.h> 2#include <iostream> 3#include <corecrt_math_defines.h> 4#include <stdio.h> 5#include <stdlib.h> 6#include "resource.h" 7#include "sslib.h" 8 9using namespace std; 10 11#pragma comment(lib, "Winmm.lib") 12 13void fft1(double ar[], double ai[], int n, int iter, int flag); 14double maxSearch(double* array, int size); 15 16#define TITLE TEXT("REC") 17#define SRATE 48000 18#define FFT_N 32768 //2^15 19 20LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { 21 static WAVEFORMATEX wfe; 22 static HWAVEOUT hWaveOut; 23 static HWAVEIN hWaveIn; 24 static int16_t* bWave1, * bWave2, * bSave, * bTmp; 25 static WAVEHDR whdr1, whdr2; 26 static DWORD dwLength = 0, dwCount; 27 static BOOL blReset = FALSE; 28 double zeroData[32768] = { 0 }; 29 30 switch (msg) { 31 case WM_DESTROY: 32 if (bSave) free(bSave); 33 PostQuitMessage(0); 34 return 0; 35 case WM_CREATE: 36 wfe.wFormatTag = WAVE_FORMAT_PCM; 37 wfe.nChannels = 1; 38 wfe.nSamplesPerSec = SRATE; 39 wfe.nAvgBytesPerSec = (wfe.nSamplesPerSec * wfe.nChannels * wfe.wBitsPerSample) / 8; 40 wfe.wBitsPerSample = 16; 41 wfe.nBlockAlign = (wfe.nChannels * wfe.wBitsPerSample) / 8; 42 wfe.cbSize = 0; 43 return 0; 44 case WM_COMMAND: 45 switch (LOWORD(wp)) { 46 case IDB_REC: 47 bWave1 = (int16_t*)malloc(SRATE*sizeof(int16_t)); 48 bWave2 = (int16_t*)malloc(SRATE* sizeof(int16_t)); 49 //dwBufferLengthと最初のmallocの整合性の確認 50 whdr1.lpData = (CHAR*)bWave1; 51 whdr1.dwBufferLength = FFT_N; 52 whdr1.dwBytesRecorded = 0; 53 whdr1.dwFlags = 0; 54 whdr1.dwLoops = 1; 55 whdr1.lpNext = NULL; 56 whdr1.dwUser = 0; 57 whdr1.reserved = 0; 58 59 whdr2.lpData = (CHAR*)bWave2; 60 whdr2.dwBufferLength = FFT_N; 61 whdr2.dwBytesRecorded = 0; 62 whdr2.dwFlags = 0; 63 whdr2.dwLoops = 1; 64 whdr2.lpNext = NULL; 65 whdr2.dwUser = 0; 66 whdr2.reserved = 0; 67 68 waveInOpen(&hWaveIn, WAVE_MAPPER, &wfe, 69 (DWORD)hWnd, 0, CALLBACK_WINDOW); 70 waveInPrepareHeader(hWaveIn, &whdr1, sizeof(WAVEHDR)); 71 waveInPrepareHeader(hWaveIn, &whdr2, sizeof(WAVEHDR)); 72 break; 73 case IDB_PLAY: 74 whdr1.lpData = (CHAR*)bSave; 75 whdr1.dwBufferLength = dwLength; 76 whdr1.dwBytesRecorded = 0; 77 whdr1.dwFlags = WHDR_BEGINLOOP | WHDR_ENDLOOP; 78 whdr1.dwLoops = 1; 79 whdr1.lpNext = NULL; 80 whdr1.dwUser = 0; 81 whdr1.reserved = 0; 82 83 waveOutOpen(&hWaveOut, WAVE_MAPPER, &wfe, 84 (DWORD)hWnd, 0, CALLBACK_WINDOW); 85 waveOutPrepareHeader( 86 hWaveOut, &whdr1, sizeof(WAVEHDR)); 87 waveOutWrite(hWaveOut, &whdr1, sizeof(WAVEHDR)); 88 break; 89 case IDB_REC_END: 90 blReset = TRUE; 91 waveInReset(hWaveIn); 92 break; 93 case IDB_PLY_END: 94 waveOutReset(hWaveOut); 95 break; 96 } 97 return 0; 98 case MM_WIM_OPEN: 99 dwLength = 0; 100 bSave = (int16_t*)realloc(bSave, 1); 101 102 EnableWindow(GetDlgItem(hWnd, IDB_PLAY), FALSE); 103 EnableWindow(GetDlgItem(hWnd, IDB_REC), FALSE); 104 EnableWindow(GetDlgItem(hWnd, IDB_REC_END), TRUE); 105 waveInAddBuffer(hWaveIn, &whdr1, sizeof(WAVEHDR)); 106 waveInAddBuffer(hWaveIn, &whdr2, sizeof(WAVEHDR)); 107 waveInStart(hWaveIn); 108 return 0; 109 case MM_WIM_DATA: 110 bTmp = (int16_t*)realloc(bSave, dwLength + ((PWAVEHDR)lp)->dwBytesRecorded); 111 if (blReset || !bTmp) { 112 waveInClose(hWaveIn); 113 blReset = FALSE; 114 115 return 0; 116 } 117 bSave = bTmp; 118 for (dwCount = 0; dwCount < ((PWAVEHDR)lp)->dwBytesRecorded; dwCount++) * (bSave + dwLength + dwCount) = *(((PWAVEHDR)lp)->lpData + dwCount); 119 dwLength += ((PWAVEHDR)lp)->dwBytesRecorded; 120 waveInAddBuffer(hWaveIn, (PWAVEHDR)lp, sizeof(WAVEHDR)); 121 122 fft1((double*)((PWAVEHDR)lp)->lpData, zeroData, (int)((LPWAVEHDR)lp)->dwBytesRecorded, 0, 0); 123 return 0; 124 case MM_WIM_CLOSE: 125 waveInUnprepareHeader(hWaveIn, &whdr1, sizeof(WAVEHDR)); 126 waveInUnprepareHeader(hWaveIn, &whdr2, sizeof(WAVEHDR)); 127 cout << "free memory" << endl; 128 free(bWave1); 129 free(bWave2); 130 131 EnableWindow(GetDlgItem(hWnd, IDB_PLAY), TRUE); 132 EnableWindow(GetDlgItem(hWnd, IDB_REC), TRUE); 133 EnableWindow(GetDlgItem(hWnd, IDB_REC_END), FALSE); 134 return 0; 135 case MM_WOM_OPEN: 136 EnableWindow(GetDlgItem(hWnd, IDB_PLAY), FALSE); 137 EnableWindow(GetDlgItem(hWnd, IDB_REC), FALSE); 138 EnableWindow(GetDlgItem(hWnd, IDB_PLY_END), TRUE); 139 return 0; 140 case MM_WOM_DONE: 141 waveOutClose(hWaveOut); 142 return 0; 143 case MM_WOM_CLOSE: 144 waveOutUnprepareHeader(hWaveOut, &whdr1, sizeof(WAVEHDR)); 145 EnableWindow(GetDlgItem(hWnd, IDB_PLAY), TRUE); 146 EnableWindow(GetDlgItem(hWnd, IDB_REC), TRUE); 147 EnableWindow(GetDlgItem(hWnd, IDB_PLY_END), FALSE); 148 return 0; 149 } 150 return DefWindowProc(hWnd, msg, wp, lp); 151} 152 153 154int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 155 PSTR lpCmdLine, int nCmdShow) { 156 HWND hwnd; 157 MSG msg; 158 WNDCLASS winc; 159 160 winc.style = CS_HREDRAW | CS_VREDRAW; 161 winc.lpfnWndProc = WndProc; 162 winc.cbClsExtra = 0; 163 winc.cbWndExtra = DLGWINDOWEXTRA; 164 winc.hInstance = hInstance; 165 winc.hIcon = LoadIcon(NULL, IDI_APPLICATION); 166 winc.hCursor = LoadCursor(NULL, IDC_ARROW); 167 winc.hbrBackground = CreateSolidBrush(GetSysColor(COLOR_MENU)); 168 winc.lpszMenuName = NULL; 169 winc.lpszClassName = TEXT("KITTY"); 170 171 cout << "dousa_kakunin" << endl; 172 173 if (!RegisterClass(&winc)) return -1; 174 175 hwnd = CreateDialog(hInstance, TEXT("KITTY"), 0, NULL); 176 177 if (hwnd == NULL) return -1; 178 179 while (GetMessage(&msg, NULL, 0, 0)) { 180 TranslateMessage(&msg); 181 DispatchMessage(&msg); 182 } 183 return msg.wParam; 184} 185 186//FFT関数 187void fft1(double ar[], double ai[], int n, int iter, int flag) 188{ 189 int i, it, j, j1, j2, k, xp, xp2; 190 double arg, dr1, dr2, di1, di2, tr, ti, w, wr, wi; 191 192 if (n < 2) 193 { 194 fprintf(stderr, "Error : n < 2 in fft1()\n"); 195 return; 196 } 197 if (iter <= 0) 198 { 199 iter = 0; 200 i = n; 201 while ((i /= 2) != 0) iter++; 202 } 203 j = 1; 204 for (i = 0; i < iter; i++) j *= 2; 205 if (n != j) 206 { 207 fprintf(stderr, "Error : n != 2 ^ k in fft1()\n"); 208 return; 209 } 210 w = (flag ? M_PI : -M_PI) / (double)n; 211 xp2 = n; 212 for (it = 0; it < iter; it++) 213 { 214 xp = xp2; 215 xp2 /= 2; 216 w *= 2; 217 for (k = 0, i = -xp; k < xp2; i++) 218 { 219 wr = cos(arg = w * k++); 220 wi = sin(arg); 221 for (j = xp; j <= n; j += xp) 222 { 223 j2 = (j1 = j + i) + xp2; 224 tr = (dr1 = ar[j1]) - (dr2 = ar[j2]); 225 ti = (di1 = ai[j1]) - (di2 = ai[j2]); 226 ar[j1] = dr1 + dr2; 227 ai[j1] = di1 + di2; 228 ar[j2] = tr * wr - ti * wi; 229 ai[j2] = ti * wr + tr * wi; 230 } 231 } 232 } 233 j = j1 = n / 2; 234 j2 = n - 1; 235 for (i = 1; i < j2; i++) 236 { 237 if (i < j) 238 { 239 w = ar[i]; 240 ar[i] = ar[j]; 241 ar[j] = w; 242 w = ai[i]; 243 ai[i] = ai[j]; 244 ai[j] = w; 245 } 246 k = j1; 247 while (k <= j) 248 { 249 j -= k; 250 k /= 2; 251 } 252 j += k; 253 } 254 if (flag == 0) return; 255 w = 1. / (double)n; 256 for (i = 0; i < n; i++) 257 { 258 ar[i] *= w; 259 ai[i] *= w; 260 } 261 return; 262} 263//最大値探索関数 264double maxSearch(double* array, int size) 265{ 266 double max = 0; 267 for (int i = 0; i < size; i++) 268 { 269 if (max < array[i]) 270 { 271 max = array[i]; 272 } 273 } 274 return max; 275}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

for (dwCount = 0; dwCount < ((PWAVEHDR)lp)->dwBytesRecorded; dwCount++) * (bSave + dwLength + dwCount) = *(((PWAVEHDR)lp)->lpData + dwCount);

c++

1memcpy(bSave + dwLength/2, ((PWAVEHDR)lp)->lpData, dwBytesRecorded);

に書き換えるとメモリ破壊はしないでしょう。


問題は、

fft1((double*)((PWAVEHDR)lp)->lpData, zeroData, (int)((LPWAVEHDR)lp)->dwBytesRecorded, 0, 0);

あなたがfft1関数を自作できないのであれば、int16_tからdoubleへの変換を行う必要があります。

c

1double* fftbuffer = (double*)malloc(sizeof(double) * (LPWAVEHDR)lp)->dwBytesRecorded /2); 2for (dwCount = 0; dwCount < ((PWAVEHDR)lp)->dwBytesRecorded/2; dwCount++) 3 fftbuffer[dwCount] = ((int16_t*)((PWAVEHDR)lp)->lpData)[dwCount]; 4fft1(fftbuffer, zeroData, ((LPWAVEHDR)lp)->dwBytesRecorded/2, 0, 0); 5free(fftbuffer);

投稿2019/11/06 09:24

asm

総合スコア15149

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

YMD_kts

2019/11/08 01:35

回答ありがとうございます 見事にヒープ破壊は起きなくなったのですが、bSave + dwLength/2や((PWAVEHDR)lp)->dwBytesRecorded/2のように、半分のデータで行う処理がなぜ必要なのか考えてもわかりませんでした... 是非教えていただけるとありがたいです
asm

2019/11/08 02:00

printf("(char*) 0 + 4 = %p\n", ((char*) 0)+4); printf("(int16_t*)0 + 4 = %p\n", ((int16_t*)0)+4); printf("(int32_t*)0 + 4 = %p\n", ((int32_t*)0)+4); それぞれ表示してみるとわかりやすいでしょうか。 ポインタに対する加減算は、ポインタが指してる型のサイズの倍数で動きます。
YMD_kts

2019/11/08 03:28

/2することで適切なサイズに揃えるということですね ありがとうございます!
YMD_kts

2019/11/20 15:09

今更質問なのですが、御回答頂いたFFTのコードを、440Hzの音声入力でテストしてみたのですが、いくら試しても半分の220Hzでピークが出てしまいます。 そこでFFTの範囲を '((LPWAVEHDR)lp)->dwBytesRecorded' でFFTしてみたところ、440Hzにピークは来るのですが今度は0Hzにもピークが現れてしまいます。しかもこの0Hzのピークは440Hzのピークより大きいです。 聞いてばかりで恐縮なのですがなにか解決できそうな知恵がございましたら御回答願いたいです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問