HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2018
0513
nitrowavファイルの結合・出力13解決


nitro

リンク

2018/5/13(Sun) 15:22:43|NO.84367

前のスレッドで書き込まれたソースを自力で動かしてみました


sdim a,1000000 sdim b,1000000 bload "1.wav",a bload "2.wav",b a_len=lpeek(a,40)//dataチャンクのサイズがわかる。 b_len=lpeek(b,40)//dataチャンクのサイズがわかる。 c_len=a_len+b_len sdim c,c_len+40//dataサイズの合計に、チャンクフォーマットのサイズを追加して。 memexpand a,a_len memexpand b,b_len memcpy c,a,int(a_len)//aの列を全部コピーして memcpy c,b,int(b_len),int(a_len)//後ろにbのデータのみをコピー bSave "c.wav",c

c.wavは出力されますが結合して出力できません
どうすればよいでしょうか
ご教授お願いします。



この記事に返信する


KA

リンク

2018/5/13(Sun) 15:57:04|NO.84368

前スレで回答のあった方法を何故使わないのですか?
独自解釈も良いのですが、明後日の方向になっています。

それと別スレにした理由は?



Velgail

リンク

2018/5/13(Sun) 15:58:30|NO.84369

まともに実験して、バグも見つけたので書き直した。
音は、
http://commons.nicovideo.jp/material/nc18547
http://commons.nicovideo.jp/material/nc18549
から取得したものをマイドキュメントに保存して実験。最小構成のWAVEファイルの場合の実験であることは変わらず。周波数・ビット数の違いとかも考えてないですよ。


chdir dir_mydoc //1つ目のファイルロード exist "nc18547.wav" a_size=strsize sdim a,a_size bload "nc18547.wav",a,a_size //2つ目のファイルロード exist "nc18549.wav" b_size=strsize sdim b,b_size bload "nc18549.wav",b,b_size a_len=lpeek(a,42)//dataチャンクのサイズがわかる。(42Byte目〜45Byte目までの4Byteが概ねDataチャンクのサイズみたい。2Byteずれてた) b_len=lpeek(b,42)//dataチャンクのサイズがわかる。 c_len=a_len+b_len sdim c,c_len+46//dataサイズの合計に、チャンクフォーマットのサイズを追加して。(上のように46だった) memcpy c,a,a_size memcpy c,b,int(b_len),int(a_len),46//後ろにbのデータのみをコピー(46ずらすのを忘れずに) lpoke c,42,c_len//これをしないとdataサイズが変わらないため、後ろのデータ列が認識されない。 bsave "c.wav",c,a_size+b_len//保存長さはc_len+46でも可。



あらや

リンク

2018/5/13(Sun) 16:11:51|NO.84370

WAVEファイルの構造がわかっておられないようなので
簡単に説明させていただくと

ファイル内部の先頭に色々とファイルの付加情報が書いてあります。

付加情報は
これはWAVE形式であるとか
ファイルサイズがいくつだとか
チャンネル数だとか
WAVEファイルの形式だとか
色々です
その付加情報の後に波形データが書いてあるのですが

付加情報の中にデータの長さが書かれていまして
その長さに応じた量しか再生されないわけです。

・通常のWAVEファイルの場合
RIFFチャンク(付加情報1)
FMTチャンク(付加情報2)
DATAチャンク(波形データ)

となっているのに対してnitroさんのソースはファイル2つをそのままくっつけただけなので

RIFFチャンク(1つ目のファイルの付加情報1)
FMTチャンク(1つ目のファイルの付加情報2)
DATAチャンク(1つ目のファイルの波形データ)
RIFFチャンク(2つ目のファイルの付加情報1)
FMTチャンク(2つ目のファイルの付加情報2)
DATAチャンク(2つ目のファイルの波形データ)

だいたいこんな感じになっています。

連結して再生するのならば、1つ目の付加情報の中にあるデータの長さを書き換えて
更に2つ目の波形データのみを後ろに連結させるといった手順が必要です。



あらや

リンク

2018/5/13(Sun) 17:13:12|NO.84371

Velgailさんのソースを適当なファイルで試したら失敗したので
申し訳ないのですが少々修正させていただきました。

lpeekのインデックスがずれていて
波形データのサイズ(DATAチャンクのサイズ)取得が失敗していたようなので
FMTチャンクサイズを取得してからDATAチャンクのサイズを取得という形にして
ファイルcのサイズやメモリコピーのインデックスもそれに合わせるように変更しました。

file_a = "1.wav" // 1つ目のファイル名 file_b = "2.wav" // 2つ目のファイル名 file_c = "c.wav" // 出力ファイル名 //1つ目のファイルロード exist file_a a_size=strsize sdim a,a_size bload file_a,a,a_size //2つ目のファイルロード exist file_b b_size=strsize sdim b,b_size bload file_b,b,b_size a_len0 = lpeek(a,16)+24 // RIFFチャンクサイズ + FMTチャンクサイズ + DATAチャンクの4バイト b_len0 = lpeek(b,16)+24 // 同上 a_len=lpeek(a, a_len0) // DATAチャンクの波形データのサイズ b_len=lpeek(b, b_len0) // 同上 c_size=a_size+b_len // 出力ファイルサイズ ファイルaのサイズ + ファイルbの波形データサイズ c_len=a_len+b_len // 2つのファイルの波形データのサイズ合計 sdim c,c_size // 出力ファイルサイズで初期化 memcpy c,a,a_size // ファイルaはそのままコピー memcpy c,b,b_len,a_size,b_len0+4 // 後ろにbのデータのみをコピー lpoke c,4,c_size-8 // ファイルサイズの更新 lpoke c,a_len0,c_len // 波形データサイズの更新 bsave file_c,c,c_size //保存 mes "連結保存終了"



nitro

リンク

2018/5/13(Sun) 22:36:57|NO.84378

お二方どうもありがとうございます
あらやさんの方法を使おうと思います。

あともう一つ質問があるのですが
ループを利用してひとつひとつ結合しようと思っているのですが
うまくいきません


*output text="あいうえお" dialog "wav",17 if stat = 0:stop count=0 repeat charalen(text) stext(cnt) = strmid(text, cnt*2, 2)//文字を一つずつわける filename="sound/"+stext(cnt)+".wav" exist filename f_size(cnt)=strsize sdim fb,f_size(cnt),charalen(text) bload filename,fb(cnt),f_size(cnt) f_len0(cnt)=lpeek(fb(cnt),16)+24 // RIFFチャンクサイズ + FMTチャンクサイズ + DATAチャンクの4バイト f_len(cnt)=lpeek(fb(cnt),f_len0(cnt)) // DATAチャンクの波形データのサイズ op_size=op_size+f_size(cnt) // 出力ファイルサイズ ファイルaのサイズ + ファイルbの波形データサイズ op_len=op_len+f_len(cnt) // 2つのファイルの波形データのサイズ合計 wait 1 loop sdim cop,op_size repeat charalen(text) if count=0{ memcpy cop,fb(0),f_size(0) // ファイルaはそのままコピー }else{ memcpy cop,fb(cnt),f_len(cnt),f_size(0),f_lent+4 // 後ろにbのデータのみをコピー } lpoke cop,4,op_size-8 // ファイルサイズの更新 lpoke cop,f_len(cnt),op_len // 波形データサイズの更新 count++ f_sizem=f_size(0) f_size2=f_size2+f_size(0) f_lent=f_lent+f_len(cnt) wait 1 loop bsave refstr,cop,op_size //保存
ひとつだけならできるのですが
もしよかったらご教授お願いします。



あらや

リンク

2018/5/13(Sun) 22:56:39|NO.84380

ちょっと理解できない所があるんですが
いくつか独自の関数(?)とか配列とか作ってます?

たぶんそのせいで完全には理解できないのですが

>sdim fb,f_size(cnt),charalen(text)
ここ、ループの中で毎回fbが初期化されているので
次のループでファイルが連結できないんじゃないでしょうか?

やるなら最初にもう一つループを作って
ファイルサイズが一番大きいファイルに合わせて
ループの外で

sdim fb,最大ファイルサイズ,charalen(text)

みたいにしないと初期化されるたびにfbの中身が消去されます。



あらや

リンク

2018/5/13(Sun) 23:59:13|NO.84381

よく見たらsdim以外の箇所も色々おかしいですね。

まず最初のループの修正

;↓これだと出力ファイルサイズが大きすぎます ;op_size=op_size+f_size(cnt) // 出力ファイルサイズ ファイルaのサイズ + ファイルbの波形データサイズ if( cnt == 0 ) { op_size = f_size(cnt) // 出力ファイルサイズ ファイルaのサイズ + ファイルbの波形データサイズ } else { op_size += f_len(cnt) } ; += の使い方も覚えておくと楽ですよ(似たような式で -= *= /= などもあります) ;op_len=op_len+f_len(cnt) // 2つのファイルの波形データのサイズ合計 op_len += f_len(cnt) // 2つのファイルの波形データのサイズ合計

次のループの修正

repeat charalen(text) if count=0{ memcpy cop,fb(cnt),f_size(cnt) // ファイルaはそのままコピー f_sizem = f_size(cnt) }else{ memcpy cop,fb(cnt),f_len(cnt),f_sizem,f_len0(cnt)+4 // 後ろにbのデータのみをコピー f_sizem += f_len(cnt) } ;この2行は固定値なので保存直前に一回やればいい ;lpoke cop,4,op_size-8 // ファイルサイズの更新 ;lpoke cop,f_len(cnt),op_len // 波形データサイズの更新 count++ ; この3行はいらないかも? ;f_sizem=f_size(0) ;f_size2=f_size2+f_size(0) ;f_lent=f_lent+f_len(cnt) wait 1 loop lpoke cop,4,op_size-8 // ファイルサイズの更新 lpoke cop,f_len0(0),op_len // 波形データサイズの更新 bsave refstr,cop,op_size //保存
これで大丈夫なのかな……?
どこか間違えていたらごめんなさい。

変数のcountは、わざわざ用意しなくてもcntで充分な気がしましたが
どこか別の箇所で使っているかもしれないので残しました。



nitro

リンク

2018/5/14(Mon) 10:15:59|NO.84384

できませんでした...
バッファオーバーフローが発生してしまいます...



MillkeyStars

リンク

2018/5/14(Mon) 13:49:34|NO.84385


【wave_1.wav】     【wave_2.wav】      【結合ファイル】 'RIFF'         'RIFF'          どちらか一方 size          size (どちらか一方 の size) + (もう一方の波形データのサイズ) 'fmt '         'fmt '          どちらか一方 size          size どちらか一方 フォーマットID     フォーマットID      どちらか一方 チャンネル数      チャンネル数       どちらか一方 サンプリングレート   サンプリングレート    どちらか一方 データ速度       データ速度        どちらか一方 ブロックサイズ     ブロックサイズ      どちらか一方 サンプルビット数    サンプルビット数     どちらか一方 'data'         'data'          どちらか一方 波形データサイズ    波形データサイズ     両方合計 波形データ       波形データ        両方結合
単純に二つのファイルから特定部分を結合・計算すれば結合されたファイルが出来上がると思うんだけど・・・
というか、wave ファイル構造調べてください。



nitro

リンク

2018/5/14(Mon) 18:18:42|NO.84388

MillkeyStarsさんわかりやすい表を作っていただきありがとうございます。
その表を参考にいろいろ試行錯誤してみましたがうまくいきませんでした

現段階でのソースはこんな感じです

*output text="あいうえお" dialog "wav",17 if stat = 0:stop count=0 repeat charalen(text) stext(cnt) = strmid(text, cnt*2, 2) filename(cnt)="sound/"+stext(cnt)+".wav" exist filename(cnt) f_size(cnt)=strsize sdim fb,f_size(cnt),charalen(text) fb(cnt)=str(fb(cnt)) wait 1 loop repeat charalen(text) bload filename(cnt),fb(cnt),f_size(cnt) f_len0(cnt)=lpeek(fb(cnt),16)+24 // RIFFチャンクサイズ + FMTチャンクサイズ + DATAチャンクの4バイト f_len(cnt)=lpeek(fb(cnt),f_len0(cnt)) // DATAチャンクの波形データのサイズ if( cnt == 0 ) { op_size = f_size(cnt) // 出力ファイルサイズ ファイルaのサイズ + ファイルbの波形データサイズ }else { op_size += f_len(cnt) } op_len += f_len(cnt) wait 1 loop sdim cop,op_size repeat charalen(text) if count=0{ memcpy cop,fb(cnt),f_size(cnt) // ファイルaはそのままコピー f_sizem = f_size(cnt) }else{ memcpy cop,fb(cnt),f_len(cnt),f_sizem,f_len0(cnt)+4 // 後ろにbのデータのみをコピー f_sizem += f_len(cnt) } ;この2行は固定値なので保存直前に一回やればいい ;lpoke cop,4,op_size-8 // ファイルサイズの更新 ;lpoke cop,f_len(cnt),op_len // 波形データサイズの更新 count++ ; この3行はいらないかも? ;f_sizem=f_size(0) ;f_size2=f_size2+f_size(0) ;f_lent=f_lent+f_len(cnt) wait 1 loop lpoke cop,4,op_size-8 // ファイルサイズの更新 lpoke cop,f_len0(0),op_len // 波形データサイズの更新 bsave refstr,cop,op_size //保存

一つのファイルなら出力できます
複数はできません
バイト数はあっているはずなのにバッファオーバーフローになってしまいます



あらや

リンク

2018/5/14(Mon) 19:29:31|NO.84391

>sdim fb,f_size(cnt),charalen(text)
繰り返しますが、ループ内でsdimをやると
ループごとに変数fbの中身が初期化されて読み込んだデータが消えます。

WAVEファイル以前にまずソースの流れを意識してみてください。

// 複数WAVEファイルの連結 op_file = "total.wav" // 出力ファイル名 // WAVEファイル一覧取得 sdim filelist, 64; dirlist filelist, "*.wav"; filenum = stat; // ファイル数 // 各種変数初期化 dim f_size, filenum; // ファイルサイズ dim f_len0, filenum; // 波形データサイズのインデックス dim f_len, filenum; // 波形データサイズ maxsize = 0; // 一番大きなファイルサイズ op_size = 0; // 出力ファイルサイズ op_len = 0; // 全てのファイルの波形データサイズの合計 notesel filelist; // ループ1 最大ファイルサイズを探す、ついでにファイルサイズ取得 repeat filenum filename = ""; noteget filename, cnt; // ファイル名取得 exist filename; f_size(cnt) = strsize; // ファイルサイズ取得 // 最大ファイルサイズを探す if( f_size(cnt) > maxsize ) { maxsize = f_size(cnt); } loop sdim fb, maxsize, filenum; // ファイルデータが入る // ループ2 ファイル読込・各データ取得・出力データ算出 repeat filenum filename = ""; noteget filename, cnt; // ファイル名取得 bload filename, fb(cnt), f_size(cnt); // ファイル読込 f_len0(cnt) = lpeek(fb(cnt), 16) + 24; // 波形データサイズのインデックス取得 f_len(cnt) = lpeek(fb(cnt), f_len0(cnt)); // 波形データサイズ取得 // 出力ファイルサイズ算出 if( cnt == 0 ) { op_size = f_size(cnt); } else { op_size += f_len(cnt); } op_len += f_len(cnt); // 全てのファイルの波形データサイズの合計値を算出 loop sdim cop, op_size; // 出力ファイルデータ // ループ3 出力ファイルデータの構築 repeat filenum if( cnt == 0 ) { memcpy cop, fb(cnt), f_size(cnt); f_sizem = f_size(cnt); } else{ memcpy cop, fb(cnt), f_len(cnt), f_sizem, f_len0(cnt)+4; f_sizem += f_len(cnt); } loop lpoke cop, 4, op_size-8; // ファイルサイズの更新 lpoke cop, f_len0(0), op_len; // 波形データサイズの更新 bsave op_file, cop, op_size; //保存 mes "連結保存終了"

Velgailさんも仰っていましたが、
ビット数とか周波数とかはまったく考慮していないので
それらが異なるファイルを連結するとうまく再生できないかもしれません。



GENKI

リンク

2018/5/14(Mon) 20:36:36|NO.84392

mod_riffモジュール
http://mclab.uunyan.com/dl/dl39.htm

スレの流れも空気も全て無視して、モジュールを使って試しに作ってみました。

#include "mod_riff.hsp" ; -------------------- ; 読み込むRIFFファイルを指定 ; -------------------- waveFName1 = "nc18547.wav" waveFName2 = "nc18549.wav" ; -------------------- ; waveのフォーマット情報を取得 ; -------------------- dim info,6 GetWaveInfo waveFName1, info mes "チャンネル数 : " + info(1) + " ch" ; -------------------- ; 波形データを取得 ; -------------------- ; チャンクの情報を取得 dim idx, 3 sdim name, 4, 3 sdim ftype, 4, 3 dim size, 3 dim pid, 3 ; ---- ; 波形データ1 ; ---- GetRiffIndex waveFName1, idx, name, ftype, size, pid ; dataチャンク検索(波形データ部分) repeat stat if name(cnt) = "data" : gwd_id = cnt loop ; バッファにデータ読み込み sdim buf1, size(gwd_id) bload waveFName1, buf1, size(gwd_id), idx(gwd_id) + 8 buf1_size = size(gwd_id) ; ---- ; 波形データ2 ; ---- GetRiffIndex waveFName2, idx, name, ftype, size, pid ; dataチャンク検索(波形データ部分) repeat stat if name(cnt) = "data" : gwd_id = cnt loop ; バッファにデータ読み込み sdim buf2, size(gwd_id) bload waveFName2, buf2, size(gwd_id), idx(gwd_id) + 8 buf2_size = size(gwd_id) ; -------------------------------- ; ; fmt チャンク ; SetRiffChunkBuffer fmtBuf, "fmt" AddRiffCkData fmtBuf, info(0), 2 ; フォーマットID AddRiffCkData fmtBuf, info(1), 2 ; チャンネル数 AddRiffCkData fmtBuf, info(2), 4 ; サンプリングレート AddRiffCkData fmtBuf, info(3), 4 ; データ速度 AddRiffCkData fmtBuf, info(4), 2 ; ブロックサイズ AddRiffCkData fmtBuf, info(5), 2 ; ビットレート CloseRiffCkData fmtBuf fmtBufSize = stat ; -------------------------------- ; ; dataチャンク ; SetRiffChunkBuffer dataBuf, "data", buf1_size+buf2_size ; 波形データ1 CopyRiffCkData dataBuf, buf1, buf1_size ; 波形データ2 CopyRiffCkData dataBuf, buf2, buf2_size, buf1_size CloseRiffCkData dataBuf dataBufSize = stat ; -------------------------------- ; ; RIFFチャンク ; ;作成したサブチャンクをRIFFチャンクに組み込みます。 ; サイズ sz = 12 ; ヘッダ sz += fmtBufSize + fmtBufSize \ 2 sz += dataBufSize + dataBufSize \ 2 ; バッファ確保 SetRiffChunkBuffer riffBuf, "RIFF", sz, "WAVE" ; 書き込み CopyRiffCkData riffBuf, fmtBuf, fmtBufSize ;fmtチャンク if fmtBufSize \ 2 : AddRiffCkData fmtBuf, 0, 2 CopyRiffCkData riffBuf, dataBuf, dataBufSize ;dataチャンク if dataBufSize \ 2 : AddRiffCkData dataBuf, 0, 2 CloseRiffCkData riffBuf riffBufSize = stat ; -------------------------------- ; ; 書き込み ; bsave "sample001.wav", riffBuf mes "WAVEフィル作成が完了しました。"
なるほど、これはなんとも使いにくいですね。
こんど暇な時に機能追加しよう。(´・ω・`)



nitro

リンク

2018/5/14(Mon) 21:21:04|NO.84395

あらやさんご丁寧にありがとうございます!
無事に機能しました!
GENKIさんもありがとうございます
今度wavについて調べてモジュール使ってみたいと思います

皆さんどうもありがとうございます!



ONION software Copyright 1997-2021(c) All rights reserved.