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


HSPTV!掲示板


未解決 解決 停止 削除要請

2019
0129
haru音声ファイルを結合して出力する7解決


haru

リンク

2019/1/29(Tue) 05:38:01|NO.86416

こんにちは。
今、音声ファイルを再生するソフトを制作していたものに追加で、
選択した音声ファイルを結合させて新たな音声ファイルを作る機能を
つけたいと考えています。
ですが調べてみても、音声ファイルを出力する方法というのが
なかなか見つからず、1つwave方式で出力するものを見つけたのですが
同じwave方式でないと結合できないそうです。
何か良い方法に思い当たる方はいないでしょうか?

*今できれば対応させたいと思っているのは、
windows mciで読み込み可能な
.wav、.aif、.mp3、.m4a、.aac、.wma、.mid

です。 もちろんすべてに対応するような万能な物があるとは考えにくいですが、 できればmp3とm4aには対応してほしいです。 *参考にさせていただいたスクリプトも記述しておきます。
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 "連結保存終了"

回答よろしくお願いします。



この記事に返信する


ZAP

リンク

2019/1/29(Tue) 20:53:01|NO.86427

前提条件がわからないのでこのままでは答えは得られそうにないです。

wavとmp3など、異なる形式の音声を結合したいのか?
その場合、出力形式はどうしたいのか?
全部wavにしたいのか?mp3にして出力するのか?

それともmp3とmp3といった、同じ形式の音声を単に結合したいのか?

前者だと自力でmp3などの圧縮音声データを一旦wavにデコードしてから結合する、
といった感じになると思います。

さらにそれをmp3に変換して出力したいとかになると、
圧縮するプログラムも自力で書かねばならず、
一般的なmp3エンコーダーソフトと同じものを再現したい!と
言っているのと同じことになります。

いずれにしても各音声ファイルのフォーマット形式を調べてそれにあった
プログラムを書く必要があり、レベルはかなり高いと思われます。



haru

リンク

2019/1/29(Tue) 23:36:39|NO.86431

ZAPさん、回答ありがとうございます。
質問内容が分かりにくくなってしまい、すいませんでした。
僕がやりたかったのは、
mp3+mp3=mp3 or wma
ということです。
wma+wma=wma(元のwmaには制限あり)
というようなスクリプトしか見つけられなかったので、
質問させて頂きました。



haru

リンク

2019/1/29(Tue) 23:37:34|NO.86432

誤字訂正
wma=wav
です。



なたで

リンク

2019/1/30(Wed) 01:01:55|NO.86433

ffmpegという外部ツールを使用してもよいのであれば、
以下のように作ることができます。
なお、midは楽譜のようなデータであり音声波形データとは異なるため対応できません。

下準備は以下のようにします。

\src\tools\ffmpeg.exe
\src\tools\LICENSE.txt
\concat_sounds.hsp

※ffmpegは以下のサイトから、32ビット版のWindows用のビルドしたものを使用します。
ffmpegのライセンスはGPLとなりますが、外部からexeを呼び出す場合は、自分のコードはGPLにしなくてもよいです。
https://www.ffmpeg.org/
https://ffmpeg.zeranoe.com/builds/

concat_sounds.hspは以下のようなコードとなります。

#include "hspext.as" tool_folder = "tools" ffmpeg_exe = dir_cur + "\\" + tool_folder + "\\" + "ffmpeg.exe" sdim sound_file_1, 500 sdim sound_file_2, 500 objsize 500, 20 input sound_file_1 button goto "音声Aを設定",*set_sound input sound_file_2 button goto "音声Bを設定", *set_sound button goto "音声Aと音声Bを結合する", *concat_sounds stop *set_sound objid = stat dialog "wav;*.mp3;*.m4a;*.aac;*.wma", 16, "音声を選択してください" if(stat != 1) { stop } objprm (objid - 1), refstr if(objid == 1) { sound_file_1 = refstr } else { sound_file_2 = refstr } stop *concat_sounds dialog "mp3", 17, "保存するファイル名を設定してください" if(stat != 1) { stop } output_file = refstr if(instr(output_file, strlen(output_file) - 4, ".mp3")) { output_file += ".mp3" } cmd = "\"" + ffmpeg_exe + "\" " cmd += "-i \"" + sound_file_1 + "\" " cmd += "-i \"" + sound_file_2 + "\" " cmd += "-filter_complex \"concat=n=2:v=0:a=1\" " cmd += "\"" + output_file + "\"" sdim ln,4096 sdim pipe_input, 128 * 1024 mes "処理中" pipeexec pipe_input, cmd, 1 repeat pipeget ln if(stat == 0) { break } await 10 loop mes "処理が完了しました" stop

【参考】
GPLでリンクしない場合の扱いについて
https://www.gnu.org/licenses/gpl-faq.html#GPLAndPlugins



haru

リンク

2019/1/30(Wed) 20:51:35|NO.86440

なたでさん、回答ありがとうございます!
動作テストも成功しました。
現在作成中のアプリケーションに使用しようと思うのですが、
(公開するとしたら)アプリケーションになたでさんのお名前を
記入しても問題ないでしょうか?



haru

リンク

2019/1/30(Wed) 20:52:29|NO.86441

解決のチェックをつけ忘れたので



なたで

リンク

2019/1/30(Wed) 21:11:36|NO.86442

解決してよかったです!
記入しても良いですし記入しなくても良いですし自由ですよー。


ところで、私のスクリプトはサンプルでして、細かいところの考慮が抜けております。
もし流用している場合は以下のような注意点があります・・・。

・pipeexec待ち中のrepeat文でボタンを押された場合
本来は、button にgosubをつけて、処理中は飛ばした先からreturnするようにする
あるいは処理中はボタンを押せないように、objgrayのようなものでボタンを押せなくする必要がある。

・ffmpeg_exe の出力時のファイル形式について
現在、拡張子に.mp3をつけているのでmp3形式になりますが、
自由にファイル名を設定できるようにすると、
拡張子をそれに合わせて入力しているかチェックを強化する必要があります。

・pipeexec で実行した ffmpeg が、音声の結合に失敗した場合を考慮していない。
これについては、exist でファイルが出力されているかみるか。
それでも無理であれば、ffmpegの出力した文字からエラーかどうか判定する
あるいは、pipeget の戻り値(StdErrorがでてる?)でなにかわかるかも?
どの方法も私は未検証ですが、より完全にするのであれば、
恐らくなりかなりする必要があると思われます。


サンプルを投げっぱなしになってしまいすみません。



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