|
|
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は出力されますが結合して出力できません
どうすればよいでしょうか
ご教授お願いします。
|
|
2018/5/13(Sun) 15:57:04|NO.84368
前スレで回答のあった方法を何故使わないのですか?
独自解釈も良いのですが、明後日の方向になっています。
それと別スレにした理由は?
|
|
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 "連結保存終了"
|
|
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で充分な気がしましたが
どこか別の箇所で使っているかもしれないので残しました。

| |
|
2018/5/14(Mon) 10:15:59|NO.84384
できませんでした...
バッファオーバーフローが発生してしまいます...
|
|
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 ファイル構造調べてください。
|
|
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さんも仰っていましたが、
ビット数とか周波数とかはまったく考慮していないので
それらが異なるファイルを連結するとうまく再生できないかもしれません。

| |
|
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フィル作成が完了しました。"
なるほど、これはなんとも使いにくいですね。
こんど暇な時に機能追加しよう。(´・ω・`)

| |
|
2018/5/14(Mon) 21:21:04|NO.84395
あらやさんご丁寧にありがとうございます!
無事に機能しました!
GENKIさんもありがとうございます
今度wavについて調べてモジュール使ってみたいと思います
皆さんどうもありがとうございます!
|
|