C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

C#でのwaveファイルの波形表示

[トピック内 14 記事 (1 - 14 表示)]  << 0 >>

■88011 / inTopicNo.1)  C#でのwaveファイルの波形表示
  
□投稿者/ akaveco (1回)-(2018/07/30(Mon) 05:12:26)

分類:[C#] 

私は、現在Visual Studioを用いて音声ファイルの波形表示をしようと試みています。使用言語はC#です。
そこでネットで調べて出てきたのが
http://tomosoft.jp/design/?p=8985
https://tomosoft.jp/design/?p=9023
のようなもので、このサイトでの方法はうまくいったのですが、対応しているのが8ビット、16ビットのモノラルとステレオのWaveファイルのみになっています。
24ビットや32ビットに対応するにはどのようにすればいいのでしょうか?

また、この方法以外でもっと効率のいい、waveファイルだけでなく、mp3やaiffなど、音声ファイル全般に対応できるような方法はないのでしょうか?

回答よろしくお願いいたします。
引用返信 編集キー/
■88020 / inTopicNo.2)  Re[1]: C#でのwaveファイルの波形表示
□投稿者/ 魔界の仮面弁士 (1748回)-(2018/07/30(Mon) 11:33:35)
No88011 (akaveco さん) に返信
> http://tomosoft.jp/design/?p=8985
> https://tomosoft.jp/design/?p=9023
> のようなもので、このサイトでの方法はうまくいったのですが、

とりあえず "fmt " チャンクと "data" チャンクだけ調べれば、
他のチャンクは読み捨ててしまっても良さそうですね。

別案として、こういう実装もありました。
https://social.msdn.microsoft.com/Forums/en-us/ccff6fd9-3b36-4aa2-a9d4-ba3a56bae88f/how-to-draw-a-wav-chart-graph-with-real-time-postion-indicator?forum=vbgeneral


> 対応しているのが8ビット、16ビットのモノラルとステレオのWaveファイルのみになっています。
> 24ビットや32ビットに対応するにはどのようにすればいいのでしょうか?

switch (waveHeader.BitPerSample) での判定が、
 case 8:
 case 16:
の 2 つしか無いからでしょうか。


8bit なら、bytes 値をそのまま渡していき、
16bit なら、2 バイト単位で渡していますので、同様にして、
24bit なら、3 バイト単位で渡すようにし、
32bit なら、4 バイト単位で渡してみては如何でしょう。

モノラルなら valuesR だけに詰め込み、
ステレオなら valuesL→R→L→R と交互に詰め込んでください。

ただし、チャンネル数は 2 や 4 ばかりではありません。
下記の『Sample WAVE files』には、6ch や 8ch の wav ファイルも掲載されていますね。
http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/


レンダリングする際には、
 8bit の場合、1 サンプルあたり 1 byte で -128 〜 +127
16bit の場合、1 サンプルあたり 2 bytes で -32,768 〜 +32,767
24bit の場合、1 サンプルあたり 3 bytes で -8,388,608 〜 +8,388,607
32bit の場合、1 サンプルあたり 4 bytes で -2,147,483,648 〜 +2,147,483,647
かと思いますが、波形データの解釈の仕方は、waveHeader.FormatID によっても左右されるようです。
http://www.web-sky.org/program/other/wave.php#format



参考までに、64 bit なファイル(Windows Media Player 非対応)として、
http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/Samples.html
にある M1F1-float64-AFsp.wav (376,112 バイト) を解析してみました。


バイナリ解析すると、こんな感じでした。
自分の見立てだと、何故か 0x5BCDB が余ってしまった…。

 [00000-00003] RIFF.ID       : 52,49,46,46 "RIFF"
 [00004-00007] RIFF.Size     : 0005BD28  (376,104 Bytes)
 [00008-0000B] RIFF.FileType : 57,41,56,45 ("WAVE")

 [0000C-0000F] Chunk.ID      : 66,6D,74,20 ("fmt ")
 [00010-00013] Chunk.Size    : 00000012 (18 Bytes)
 [00014-00015] フォーマットID: 0003 (IEEE float format)
 [00016-00017] チャンネル数  : 0002 (ステレオ)
 [00018-0001B] 標本化周波数  : 00001F40 (8000 Hz = 8kHz)
 [0001C-0001F] 秒間バイト数  : 0001F400 (128000)
 [00020-00021] ブロックサイズ: 0010 (16 Bytes)
 [00022-00023] 量子化ビット数: 0040 (64bit)
 [00024-00025] 拡張部サイズ  : 00,00 (なし)

 [00026-00029] Chunk.ID      : 66,61,63,74 ("fact")
 [0002A-0002D] Chunk.Size    : 00000004 (4 Bytes)
 [0002E-00031] 全サンプル数  : 00005BC5 (23,493)

 [00032-00035] Chunk.ID      : 64,61,74,61 ("data")
 [00036-00039] Chunk.Size    : 0005BC50 (375,888 Bytes)
 [0003A-5BC89] 波形データ    : ★★

 [5BC8A-5BC5D] Chunk.ID      : 61,66,73,70 ("afsp")
 [5BC5E-5BC91] 00000049      : 00000049 (73 Bytes)
 [5BC92-5BCDA] AFspデータ    : ("AFspdate: 2003-01-30 03:28:50 UTC\0user: kabal@CAPELLA\0program: CopyAudio\0")

 [5BCDB-5BCDB] 00

 [5BCDC-5BCDF] Chunk.ID      : 4C,49,53,54 ("LIST")
 [5BCE0-5BCE3] Chunk.Size    : 0000004C (76 Bytes)
 [5BCE4-5BCE7] LISTタイプ    : 49,4E,46,4F ("INFO")
 [5BCE8-5BCEB] SubChunk.ID   : 49,43,52,44 ("ICRD")
 [5BCEC-5BCEF] SubChunk.Size : 00000018 (24 Bytes)
 [5BCF0-5BD07] SubChunk.Data : ("2003-01-30 03:28:50 UTC\0")
 [5BD08-5BD0B] Subchunk.ID   : 49,53,46,54 ("ISFT")
 [5BD0C-5BD0F] SubChunk.Size : 0000000A (10 Bytes)
 [5BD10-5BD19] SubChunk.Data : ("CopyAudio\0")
 [5BD1A-5BD1D] Subchunk.ID   : 49,43,4D,54 ("ICMT")
 [5BD0E-5BD20] SubChunk.Size : 0000000E (14 Bytes)
 [5BD22-5BD2F] SubChunk.Data : ("kabal@CAPELLA\0")

引用返信 編集キー/
■88027 / inTopicNo.3)  Re[2]: C#でのwaveファイルの波形表示
□投稿者/ akaveco (3回)-(2018/07/30(Mon) 12:41:42)
No88020 (魔界の仮面弁士 さん) に返信

魔界の仮面弁士さん、返信ありがとうございます。

> switch (waveHeader.BitPerSample) での判定が、
>  case 8:
>  case 16:
> の 2 つしか無いからでしょうか。

この部分にcase 24やcase 32などと追加するのは、なんとなくわかるのですが、
具体的にどうのように追加すればいいのでしょうか?

試しに
byte[] data4 = new byte[4];と追加し

switch (waveHeader.BitPerSample)での判定に

case 24:
                            Array.Copy(waveData, frameIndex, data4, 0, 3);
                            work = (int)BitConverter.ToInt32(data4, 0);
                            frameIndex += 3;
                            break;
case 32:
                            Array.Copy(waveData, frameIndex, data4, 0, 4);
                            work = (int)BitConverter.ToInt32(data4, 0);
                            frameIndex += 4;
                            break;

と追加してみたのですがうまくいきません。

よろしくお願いします。

引用返信 編集キー/
■88041 / inTopicNo.4)  Re[3]: C#でのwaveファイルの波形表示
□投稿者/ 魔界の仮面弁士 (1753回)-(2018/07/30(Mon) 17:24:41)
No88027 (akaveco さん) に返信
>> switch (waveHeader.BitPerSample) での判定が、
>>  case 8:
>>  case 16:
>> の 2 つしか無いからでしょうか。
> この部分にcase 24やcase 32などと追加するのは、なんとなくわかるのですが、
> 具体的にどうのように追加すればいいのでしょうか?

詳しく調べたわけではないので、間違ってるかも知れませんが:


たとえば元データが
 var data = new byte[]{ 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0xFE, 0xDC, 0xBA, 0x98, …};
だとして、ステレオチャンネルで分解する場合は、
 case 8:
  dataL = new byte[] { 0x12,       0x56,       0x9A,       0xDE,       0xFE,       0xBA,       …};
  dataR = new byte[] {       0x34,       0x78,       0xBC,       0xF0,       0xDC,       0x98, …};
  break;
 case 16:
  dataL = new byte[] { 0x12, 0x34,             0x9A, 0xBC,             0xFE, 0xDC,             …};
  dataR = new byte[] {             0x56, 0x78,             0xDE, 0xF0,             0xBA, 0x98, …};
  break;
 case 24:
  dataL = new byte[] { 0x12, 0x34, 0x56,                   0xDE, 0xF0, 0xFE,                   …};
  dataR = new byte[] {                   0x78, 0x9A, 0xBC,                   0xDC, 0xBA, 0x98, …};
  break;
 case 32:
  dataL = new byte[] { 0x12, 0x34, 0x56, 0x78,                         0xFE, 0xDC, 0xBA, 0x98, …};
  dataR = new byte[] {                         0x9A, 0xBC, 0xDE, 0xF0,                         …};
  break;
のように割り振られていくと思います。Left→Right の順に並んでいるそうなので。

先のサンプルでは chanelIndex == 1 の時に Left 系配列、
chanelIndex == 2 だと Right 系配列に代入していっていますね。

ただし上記は、PCM 系フォーマットの場合の話。
各チャンネルにどの要素音が割り当てられるのかは、音声フォーマットによっても
異なるようなので、先の URL からリンクされている下記の資料も読んでおいた方が良さそうです。
http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/Docs/multichaudP.pdf


一方、各チャンネルにおけるバイナリから波形データへの復元については、ビット数に応じて
 case 8:
  SByte int8 = (sbyte)data[n];
  n++;
  break;
 case 16:
  Int16 int16 = BitConverter.ToInt16(data, n);
  n += 2;
  break;
 case 24:
  data4[0] = data[n + 0];
  data4[1] = data[n + 1];
  data4[2] = data[n + 2];
  data4[3] = (byte)0;
  Int32 int24 = BitConverter.ToInt32(data4, 0);
  n += 3;
  break;
 case 32:
  Int32 int32 = BitConverter.ToInt32(data4, n);
  n += 4;
  break;
のようなイメージになると思います。先のサンプルでは、変換結果を
 int work;  // この変数が、上記の int8, int16, int24, int32 に相当
 int[] valuesL;
 int[] valuesR;
へ代入しているようなので、適宜読み替えてみてください。


もしも PCM 系フォーマットではなく、float 系フォーマットだった場合には、
BitConverter.ToInt16 の代わりに BitConverter.ToSingle が使えるのかな…。

引用返信 編集キー/
■88055 / inTopicNo.5)  Re[4]: C#でのwaveファイルの波形表示
□投稿者/ akaveco (5回)-(2018/07/31(Tue) 11:34:44)
No88041 (魔界の仮面弁士 さん) に返信

>  case 8:
>   SByte int8 = (sbyte)data[n];
>   n++;
>   break;
>  case 16:
>   Int16 int16 = BitConverter.ToInt16(data, n);
>   n += 2;
>   break;
>  case 24:
>   data4[0] = data[n + 0];
>   data4[1] = data[n + 1];
>   data4[2] = data[n + 2];
>   data4[3] = (byte)0;
>   Int32 int24 = BitConverter.ToInt32(data4, 0);
>   n += 3;
>   break;
>  case 32:
>   Int32 int32 = BitConverter.ToInt32(data4, n);
>   n += 4;
>   break;
> のようなイメージになると思います。先のサンプルでは、変換結果を
>  int work;  // この変数が、上記の int8, int16, int24, int32 に相当
>  int[] valuesL;
>  int[] valuesR;
> へ代入しているようなので、適宜読み替えてみてください。

提案いただいたやり方でやってみても、どうもうまくいきません。
一応描画はされるのですが、明らかにそのファイルの波形とは似ても似つかない、矩形波のような繰り返しが出てきます。

モノラルでもステレオでも同じような図が描画されるので、チャンネルの割り当て時の問題ではないみたいです。
分析に使用している、音声フォーマットはおそらくPCMだと思います。
バイナリエディタで見てみたところ以下のようになっていました。

52 49 46 46 86 5E 00 00 57 41 56 45 66 6D 74 20 
10 00 00 00 01 00 01 00 44 AC 00 00 CC 04 02 00 
03 00 18 00 64 61 74 61 62 5E 00 00 5E 72 01 20

以下のサイトでの
http://sky.geocities.jp/kmaedam/directx9/waveform.html
フォーマットIDにあたるところが01 00なのでPCMだと思われます。

引用返信 編集キー/
■88083 / inTopicNo.6)  Re[5]: C#でのwaveファイルの波形表示
□投稿者/ 魔界の仮面弁士 (1757回)-(2018/08/01(Wed) 17:38:19)
No88055 (akaveco さん) に返信
> バイナリエディタで見てみたところ以下のようになっていました。
> 
> 52 49 46 46 86 5E 00 00 57 41 56 45 66 6D 74 20 
> 10 00 00 00 01 00 01 00 44 AC 00 00 CC 04 02 00 
> 03 00 18 00 64 61 74 61 62 5E 00 00 5E 72 01 20

上記 3 行のデータ末尾の 4 バイトに「5E,72,01,**」となので、
最初の音は 0x1725E すなわち「+94,814」かと思いますが、正しいでしょうか?


 [00000-00003] RIFF.ID       : 52,49,46,46 "RIFF"
 [00004-00007] RIFF.Size     : 00005E86 (24,198 Bytes)
 [00008-0000B] RIFF.FileType : 57,41,56,45 ("WAVE")

 [0000C-0000F] Chunk.ID      : 66,6D,74,20 ("fmt ")
 [00010-00013] Chunk.Size    : 00000010 (16 Bytes)
 [00014-00015] フォーマットID: 0001 (WAVE_FORMAT_PCM)
 [00016-00017] チャンネル数  : 0001 (モノラル)
 [00018-0001B] 標本化周波数  : 0000AC44 (44100 Hz = 44.1 kHz)
 [0001C-0001F] 秒間バイト数  : 000204CC (132,300)
 [00020-00021] ブロックサイズ: 0003 (3 Bytes = 24bit)
 [00022-00023] 量子化ビット数: 0018 (24bit)

 [00024-00027] Chunk.ID      : 64,61,74,61 ("data")
 [00028-0002B] Chunk.Size    : 00005E62 (24,162 Bytes)
 [0002C-05E89] 波形データ    : 5E,72,01,20 ……



> 提案いただいたやり方でやってみても、どうもうまくいきません。
あー。24bit の負数処理忘れて、符号なしになってますね

// data4[3] = 0;
data4[3] = (byte)((data[n + 2] > 0xF) ? 0xff : 0x00);

に訂正しておいてください。



符号付き 24bit 整数型の場合:
 0x000000 =  0
 0x000001 = +1
 0x000002 = +2
   :
 0x7FFFFD = +8,388,605
 0x7FFFFE = +8,388,606
 0x7FFFFF = +8,388,607
 0x800000 = -8,388,608
 0x800001 = -8,388,607
 0x800002 = -8,388,606
   :
 0xFFFFFD = -3
 0xFFFFFE = -2
 0xFFFFFF = -1


符号なし 24bit 整数型の場合:
 0x000000 =  0
 0x000001 = +1
 0x000002 = +2
   :
 0x7FFFFD = +8,388,605
 0x7FFFFE = +8,388,606
 0x7FFFFF = +8,388,607
 0x800000 = +8,388,608
 0x800001 = +8,388,609
 0x800002 = +8,388,610
   :
 0xFFFFFD = +16,777,213
 0xFFFFFE = +16,777,214
 0xFFFFFF = +16,777,215

引用返信 編集キー/
■88093 / inTopicNo.7)  Re[6]: C#でのwaveファイルの波形表示
□投稿者/ akaveco (7回)-(2018/08/02(Thu) 12:00:03)
No88083 (魔界の仮面弁士 さん) に返信

たびたびお付き合いいただきありがとうございます。

> 上記 3 行のデータ末尾の 4 バイトに「5E,72,01,**」となので、
> 最初の音は 0x1725E すなわち「+94,814」かと思いますが、正しいでしょうか?

そうです。1725Eでした。


> あー。24bit の負数処理忘れて、符号なしになってますね

符号あり、なしがあるんですね。知りませんでした。


> // data4[3] = 0;
> data4[3] = (byte)((data[n + 2] > 0xF) ? 0xff : 0x00);

この部分は、符号ありに変換しているということでしょうか?


この部分を変更してやってみたのですが、だいぶ元の波形に近づいたように見えるのですが、なんだか最初のほうの値が負のほうに片寄っていて、おかしなことに…
何がいけないのかわかりますでしょうか?

以下のリンクに画像をアップしました。
https://drive.google.com/file/d/16DXZALxyiD66_AcKWFflTId9U47pzJtK/view?usp=sharing
1番目が波形描画を行ったもので、
2番目がそれを最大値を大きく設定して、遠目に見たものです。
3番目が元の音声を別のプレイヤーで再生したときの波形です。
引用返信 編集キー/
■88103 / inTopicNo.8)  Re[7]: C#でのwaveファイルの波形表示
□投稿者/ 魔界の仮面弁士 (1760回)-(2018/08/02(Thu) 17:34:53)
No88093 (akaveco さん) に返信
>> 上記 3 行のデータ末尾の 4 バイトに「5E,72,01,**」となので、
>> 最初の音は 0x1725E すなわち「+94,814」かと思いますが、正しいでしょうか?
> そうです。1725Eでした。

ここが重要なところなので、再度確認。

他のソフトで「正しい」波形を見た場合も、最初のデータは
94,814 (0x1725E) 付近としてレンダリングされたということでしょうか?
6,189,569 (0x5E7201) ではなく。


> 符号あり、なしがあるんですね。

変換元のデータが
 var data  = new byte[] { 0x9A, 0xBC, 0xDE, };
の順で記録されていた場合、24bit整数型としては、
 リトルエンディアン(符号付き) = 0xDEBC9A = -2,179,942 (Int32  なら 0xFFDEBC9A 相当)
 リトルエンディアン(符号なし) = 0xDEBC9A = 14,597,274 (UInt32 なら 0x00DEBC9A 相当)
 ビッグエンディアン(符号付き) = 0x9ABCDE = -6,636,322 (Int32  なら 0xFF9ABCDE 相当)
 ビッグエンディアン(符号なし) = 0x9ABCDE = 10,140,894 (UInt32 なら 0x009ABCDE 相当)
の 4 通りの意味がありえるかと思います。

なお上記では、符号付の場合の負数表現を、2 の補数としています。(下記参照)
https://ja.wikipedia.org/wiki/%E7%AC%A6%E5%8F%B7%E4%BB%98%E6%95%B0%E5%80%A4%E8%A1%A8%E7%8F%BE


そして Windows では、バイト順をリトルエンディアンで扱いますが、
16bit の PCM フォーマットもまた、リトルエンディアンらしいです。
https://www.wdic.org/w/TECH/WAV

そのため、24bit でも同じであろうと予想して、上記のケースでは
9A,BC,DE = 0xDEBC9A = -2,179,942 と解釈してみました。


しかし、ビデオDVD の 24bit リニア PCM では、ビッグエンディアンらしいです。
(44.1kHz ではなく、48kHz と 96kHz らしいですが)
https://wiki.multimedia.cx/index.php/PCM#24-Bit_PCM
この場合には、9A,BC,DE = 0x9ABCDE = -6,636,322 と変換することになりそうです。


>> data4[3] = (byte)((data[n + 2] > 0xF) ? 0xff : 0x00);
> この部分は、符号ありに変換しているということでしょうか?

そのつもりで書きました。ただしリトルエンディアンの場合ですけれども。
24bit 値を Int32 に収めるために、不足する 1 バイト分を補っています。


> だいぶ元の波形に近づいたように見えるのですが、

グラフに描くサンプル数(データの個数)は 8054 個でしょうか。
(再生時間としては 182.6 ミリ秒程度?)


> なんだか最初のほうの値が負のほうに片寄っていて、おかしなことに…

試しに、ビッグエンディアンとして読み取ってみたら、どうなりますか?

引用返信 編集キー/
■88104 / inTopicNo.9)  Re[8]: C#でのwaveファイルの波形表示
□投稿者/ akaveco (9回)-(2018/08/02(Thu) 21:19:22)
No88103 (魔界の仮面弁士 さん) に返信

> 他のソフトで「正しい」波形を見た場合も、最初のデータは
> 94,814 (0x1725E) 付近としてレンダリングされたということでしょうか?
> 6,189,569 (0x5E7201) ではなく。

他のソフトというのは、ただの音楽プレイヤーなので、おそらくデータの確認はできないと思います。

> グラフに描くサンプル数(データの個数)は 8054 個でしょうか。
> (再生時間としては 182.6 ミリ秒程度?)

そうです。あってます。
以下はデータを出力したものです。
https://drive.google.com/file/d/1jQGRPR-jEBi0kYJlkTOKh4BmT_JnH4Kk/view?usp=sharing

ちなみに元の音声ファイルはこれです。
https://drive.google.com/file/d/11AbCl98GOLgzrQHbRKWIDFB8JFgd1caZ/view?usp=sharing

> 試しに、ビッグエンディアンとして読み取ってみたら、どうなりますか?

すみません。わからなくて…、どうやるんでしょう?
引用返信 編集キー/
■88138 / inTopicNo.10)  Re[9]: C#でのwaveファイルの波形表示
□投稿者/ 魔界の仮面弁士 (1763回)-(2018/08/04(Sat) 00:54:26)
No88104 (akaveco さん) に返信
> data4[3] = (byte)((data[n + 2] > 0xF) ? 0xff : 0x00);

原因判明!!
投稿時に盛大な転記ミスしてました。ごめんなさい。

正しくは
 data4[3] = (byte)((data[n + 2] > 0x7F) ? 0xff : 0x00);
ですね…。


> 以下はデータを出力したものです。
> https://drive.google.com/file/d/1jQGRPR-jEBi0kYJlkTOKh4BmT_JnH4Kk/view?usp=sharing
> 73
> value : FF2B68DF
> 74
> value : FF7FFFFF
> 75
> value : FF52600D

ということで、符号処理でミスってました。申し訳ない。
3〜4文字目が 80〜FF の時は、1〜2 文字目が FF になり、
3〜4文字目が 00〜7F の時は、1〜2 文字目が 00 でなければなりません。

…ということで、上記は、
#73 が 0x002B68DF
#74 が 0x007FFFFF
#75 が 0x0052600D
となるべきでした。#74 は24bit整数の最大値を指していますね。



> 他のソフトというのは、ただの音楽プレイヤーなので、おそらくデータの確認はできないと思います。

私自身も、Wave フォーマットに詳しいわけではないので、
ひとまず Sazanami というソフトをインストールして確認してみました。

下図は、最初から 90 サンプル(2.041ミリ秒弱)までを拡大表示してみたところです。
74 番目のサンプルが、最大値(1.0)を指していることがわかります。

http://www.vb-user.net/junk/replySamples/2018.08.04.00.51/90.png


前後の値も、最大値に対する割合で算出してみると、

#73 は 0x2B68DF で 0.3391379522249642 相当
#74 は 0x7FFFFF で 1.0000000000000000 相当
#75 は 0x52600D で 0.6435563139386551 相当

…ということになり、上記波形図と合致しますね。


> 0
> value : 1725E
0x1725E ÷ 0x7FFFFF = 94814 ÷ 8388607 ≒ 0.0113027109268559

波形の #0 も 0.113 付近だったので、大きくズレてはいなさそう。
http://www.vb-user.net/junk/replySamples/2018.08.04.00.51/0.png



次に確認するべきは負数領域。
これは冒頭の #1〜#3 のサンプルが使えます。

> 1
> value : FFFEA120
> 2
> value : FFFA2DA9
> 3
> value : FFFF2443

#1 は 0xFFFEA120 =  -89824 で、約 -0.0107
#2 は 0xFFFA2DA9 = -381527 で、約 -0.0455
#3 は 0xFFFF2443 =  -56253 で、約 -0.0067

これも正しいようです。
http://www.vb-user.net/junk/replySamples/2018.08.04.00.51/1_3.png
http://www.vb-user.net/junk/replySamples/2018.08.04.00.51/2.png

引用返信 編集キー/
■88141 / inTopicNo.11)  Re[10]: C#でのwaveファイルの波形表示
□投稿者/ akaveco (11回)-(2018/08/04(Sat) 16:38:27)
No88138 (魔界の仮面弁士 さん) に返信
> 正しくは
>  data4[3] = (byte)((data[n + 2] > 0x7F) ? 0xff : 0x00);
> ですね…。

0x7Fにしたら、できました!
どうもありがとうございました。
いろいろ確認作業もしていただいて、お手間を取らせて申し訳ありません。

ついでで申し訳ありませんが、32bitについてはどのようにすればいいのでしょうか?


32bitでも同様に符号の処理が必要なのでしょうか?


32bitモノラルのこの音声ファイルを描画すると
https://drive.google.com/file/d/1Ce0fbeHXJo5SWllIjMCg1u7QeHAOIVkn/view?usp=sharing

例のごとく波形がこんな感じで、
https://drive.google.com/file/d/1_z2nDiz5xg3Oru4y7Of1_wxx1hNvhU3M/view?usp=sharing

データがこれです。
https://drive.google.com/file/d/1pBWf2EPyAmK0lPNusb2wUd7Ca8SpKdEj/view?usp=sharing
引用返信 編集キー/
■88147 / inTopicNo.12)  Re[11]: C#でのwaveファイルの波形表示
□投稿者/ 魔界の仮面弁士 (1768回)-(2018/08/05(Sun) 05:08:12)
No88141 (akaveco さん) に返信
> 0x7Fにしたら、できました!
誤記でお手数をおかけしました…!
掲示板投稿時にうっかり一文字消してしまっていたらしく、
そのまま気が付きませんで。orz


> いろいろ確認作業もしていただいて、お手間を取らせて申し訳ありません。
実データを提供してもらえたので、検証しやすかったです。


> ついでで申し訳ありませんが、32bitについてはどのようにすればいいのでしょうか?
元データが DC,FB,6E,BA だった場合、PCM なら符号付き整数型のはずなので、
 ビッグエンディアンなら 0xDCFB6EBA すなわち -587,501,894
 リトルエンディアンなら 0xBA6EFBDC すなわち -1,167,131,684
になるということです。通常はリトルエンディアンの並びになるはず。


> 32bitでも同様に符号の処理が必要なのでしょうか?
リトルエンディアンであれば、そのまま BitConverter.ToInt32 だけで良いはずです。
 Int32 int32_LE = BitConverter.ToInt32(data4, n);

仮にビッグエンディアンなら、[0][1][2][3] を [3][2][1][0] の順で渡すことになるので、
 Int32 int32_BE = BitConverter.ToInt32(data4.Skip(n).Take(4).Reverse().ToArray(), 0);
といった感じになります。あるいは下記のようにも書けます。
 Int32 int32_BE = System.Net.IPAddress.NetworkToHostOrder(int32_LE);


> 32bitモノラルのこの音声ファイルを描画すると
> https://drive.google.com/file/d/1Ce0fbeHXJo5SWllIjMCg1u7QeHAOIVkn/view?usp=sharing
うっ…。Sazanami では対応していないフォーマットでした。
他に波形を拡大表示できるソフトは無いですかね。

ひとまず手動解析してみましたが、
これは WAVE_FORMAT_PCM フォーマットではなく、
WAVE_FORMAT_IEEE_FLOAT フォーマットですよね?

 [00000-00003] RIFF.ID       : 52,49,46,46 "RIFF"
 [00004-00007] RIFF.Size     : 0006BACC (441,036 Bytes)
 [00008-0000B] RIFF.FileType : 57,41,56,45 ("WAVE")

 [0000C-0000F] Chunk.ID      : 66,6D,74,20 ("fmt ")
 [00010-00013] Chunk.Size    : 00000010 (16 Bytes)
 [00014-00015] フォーマットID: 0003 (WAVE_FORMAT_IEEE_FLOAT)
 [00016-00017] チャンネル数  : 0001 (モノラル)
 [00018-0001B] 標本化周波数  : 0000AC44 (44100 Hz = 44.1 kHz)
 [0001C-0001F] 秒間バイト数  : 0002B110 (176,400)
 [00020-00021] ブロックサイズ: 0004 (4 Bytes = 32bit)
 [00022-00023] 量子化ビット数: 0020 (32bit)

 [00024-00027] Chunk.ID      : 64,61,74,61 ("data")
 [00028-0002B] Chunk.Size    : 0006BAA8 (441,000 Bytes)
 [0002C-6BAD3] 波形データ    : ★★


なのでこの場合は、整数として処理してはマズイと思います。
4 バイト単位で BitConverter.ToInt32 するのではなく、
4 バイト単位で BitConverter.ToSingle すると良いのかも。
(手持ちのソフトでは正しい波形が分からないので、確認はできませんが)


ひとまず、提供いただいた 32bit.txt ファイルの内容から
かきおこしてみると、こんな感じになりますね。

【ファイル全体(2.50秒)】
http://www.vb-user.net/junk/replySamples/2018.08.05.04.36/IEEE_FLOAT_2500.png

【0.00 秒〜0.50秒区間】
http://www.vb-user.net/junk/replySamples/2018.08.05.04.36/IEEE_FLOAT_500.png

【0.00 秒〜0.01秒区間】
http://www.vb-user.net/junk/replySamples/2018.08.05.04.36/IEEE_FLOAT_10.png

※ StepLine チャートで描画させています。
※ ChartAreas[0] は、BitConverter.ToInt32 による変換結果です。
※ ChartAreas[1] は、BitConverter.ToSingle による変換結果です。
※ AxisY.ScaleBreakStyle.Enabled = true; を指定してあります。

引用返信 編集キー/
■88179 / inTopicNo.13)  Re[12]: C#でのwaveファイルの波形表示
□投稿者/ akaveco (13回)-(2018/08/08(Wed) 09:50:42)
No88147 (魔界の仮面弁士 さん) に返信

> なのでこの場合は、整数として処理してはマズイと思います。
> 4 バイト単位で BitConverter.ToInt32 するのではなく、
> 4 バイト単位で BitConverter.ToSingle すると良いのかも。

float型で処理してみると無事成功しました!
無知な私に長々とお付き合いいただきありがとうございました。

ものすごく助かりました!!
ありがとうございます。
引用返信 編集キー/
■88180 / inTopicNo.14)  Re[13]: C#でのwaveファイルの波形表示
□投稿者/ akaveco (15回)-(2018/08/08(Wed) 09:51:02)
No88179 (akaveco さん) に返信
> ■No88147 (魔界の仮面弁士 さん) に返信
>
>>なのでこの場合は、整数として処理してはマズイと思います。
>>4 バイト単位で BitConverter.ToInt32 するのではなく、
>>4 バイト単位で BitConverter.ToSingle すると良いのかも。
>
> float型で処理してみると無事成功しました!
> 無知な私に長々とお付き合いいただきありがとうございました。
>
> ものすごく助かりました!!
> ありがとうございます。
解決済み
引用返信 編集キー/

このトピックをツリーで一括表示


トピック内ページ移動 / << 0 >>

このトピックに書きこむ