録音について

1,908 views
Skip to first unread message

gaku871

unread,
Oct 18, 2011, 1:44:01 PM10/18/11
to 日本Androidの会
投稿失礼します。
現在さまざまなサイトを参考にさせていただきながら録音のできるアプリを作ろうとしています。
wav形式のファイルを出力することはできたのですが、「ざー」という音しか流れません。
おそらく録音の段階で問題が発生しているのではないかと思うのですが、問題点を教えていただけないでしょうか。

以下ソースコード

import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

import android.app.Activity;
import android.graphics.Color;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.LinearLayout;


public class KitakoreActivity extends Activity implements
View.OnClickListener {

private final static int
WC=LinearLayout.LayoutParams.WRAP_CONTENT;

//サンプルレート 44.1kHz
private static final int SOUND_RATE = 44100;
//バッファサイズを求める
int bufferSizeRecord = AudioRecord.getMinBufferSize(SOUND_RATE,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT);
//オーディオレコードの設定
AudioRecord audioRecord = new
AudioRecord(MediaRecorder.AudioSource.MIC,
SOUND_RATE,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT,
bufferSizeRecord);

//起動時に呼び出し
@Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
requestWindowFeature(Window.FEATURE_NO_TITLE);

//レイアウトの生成
LinearLayout layout=new LinearLayout(this);
layout.setBackgroundColor(Color.rgb(255,255,255));
layout.setOrientation(LinearLayout.VERTICAL);
setContentView(layout);

//ボタンの生成
layout.addView(makeButton("録音","0"));
}

//ボタンの生成(1)
private Button makeButton(String text,String tag) {
Button button=new Button(this);
button.setText(text);
button.setTag(tag);
button.setOnClickListener(this);//ボタンクリックイベントの処理(2)
button.setLayoutParams(new LinearLayout.LayoutParams(WC,WC));
return button;
}


@Override
public void onClick(View view) {

int tag=Integer.parseInt((String)view.getTag());
if (tag==0) {//ボタンが押されたら

short[] bufferRecord = new short[bufferSizeRecord];


// 録音用ファイル取得 SDカード状態チェック略
File recFile = new
File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/
aaa/rec.raw");

try {
recFile.createNewFile();
// ファイル書き込み
FileOutputStream out = new FileOutputStream(recFile);
BufferedOutputStream bos = new BufferedOutputStream(out);
DataOutputStream dos = new DataOutputStream(bos);
audioRecord.startRecording();
// 録音開始
for(int i=0;i<50;i++){
// バッファを読み込んで書き込む
int bufferReadResult = audioRecord.read(bufferRecord,
0,bufferSizeRecord);
for(int j = 0 ; j < bufferReadResult ; j++){
dos.writeShort(bufferRecord[j]);
}
}
// 終了処理
audioRecord.stop();
out.close();
out = null;

// WAVファイル
File wavFile = new
File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/
aaa/rec.wav");
// ストリーム
FileInputStream in = new FileInputStream(recFile);
FileOutputStream ok = new FileOutputStream(wavFile);

// ヘッダ作成 サンプルレート8kHz
byte[] header = createHeader(44100,
(int)recFile.length());
// ヘッダの書き出し
ok.write(header);

// 録音したファイルのバイトデータ読み込み
int n = 0,offset = 0;
byte[] buffer = new byte[(int)recFile.length()];
while (offset < buffer.length
&& (n = in.read(buffer, offset, buffer.length -
offset)) >= 0) {
offset += n;
}
// バイトデータ書き込み
ok.write(buffer);

// 終了
in.close();
ok.close();



} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}


}
}

private byte[] createHeader(int sampleRate, int datasize) {
byte[] byteRIFF = {'R', 'I', 'F', 'F'};
byte[] byteFilesizeSub8 = intToBytes((datasize + 36)); // ファイルサイ
ズ-8バイト数
byte[] byteWAVE = {'W', 'A', 'V', 'E'};
byte[] byteFMT_ = {'f', 'm', 't', ' '};
byte[] byte16bit = intToBytes(16); // fmtチャンクのバイ
ト数
byte[] byteSamplerate = intToBytes(sampleRate); // サンプルレート
byte[] byteBytesPerSec = intToBytes(sampleRate * 2); // バイト/秒
= サンプルレート x 1チャンネル x 2バイト
byte[] bytePcmMono = {0x01, 0x00, 0x01, 0x00}; // フォーマットID
1 =リニアPCM , チャンネル 1 = モノラル
byte[] byteBlockBit = {0x02, 0x00, 0x10, 0x00}; // ブロックサイズ2バイ
ト サンプルあたりのビット数16ビット
byte[] byteDATA = {'d', 'a', 't', 'a'};
byte[] byteDatasize = intToBytes(datasize); // データサイズ

ByteArrayOutputStream ok = new ByteArrayOutputStream();
try {
ok.write(byteRIFF);
ok.write(byteFilesizeSub8);
ok.write(byteWAVE);
ok.write(byteFMT_);
ok.write(byte16bit);
ok.write(bytePcmMono);
ok.write(byteSamplerate);
ok.write(byteBytesPerSec);
ok.write(byteBlockBit);
ok.write(byteDATA);
ok.write(byteDatasize);

} catch (IOException e) {
return ok.toByteArray();
}

return ok.toByteArray();
}
public static byte[] intToBytes(int value) {
byte[] bt = new byte[4];
bt[0] = (byte)(value & 0x000000ff);
bt[1] = (byte)((value & 0x0000ff00) >> 8);
bt[2] = (byte)((value & 0x00ff0000) >> 16);
bt[3] = (byte)((value & 0xff000000) >> 24);
return bt;
}

}

ohisamallc

unread,
Oct 18, 2011, 9:23:27 PM10/18/11
to android-g...@googlegroups.com
山形のohisamaです。
山形は、秋晴れです。
がんばろう、東北。

問題を切り分ける為に、
sin波を突っ込んで見ました。

for (int i = 0; i < 2048 * 10; i++)
{
double x = 1. + 0.9 * Math.sin(2.0 * 3.1415926 * i / (44100. / 523.25));
short b = (short) (x * 128.);
dos.writeShort(b);
}

音が出ましたので、wavファイルの
生成に問題は、無いと思います。
自分は、ここまで。


> -----Original Message-----
> From: android-g...@googlegroups.com
> [mailto:android-g...@googlegroups.com]On Behalf Of gaku871
> Sent: Wednesday, October 19, 2011 2:44 AM
> To: 日本Androidの会
> Subject: [work] [android-group-japan: 14824] 録音について
>
>
> 投稿失礼します。
> 現在さまざまなサイトを参考にさせていただきながら録音のできるアプリを作ろう
> としています。
> wav形式のファイルを出力することはできたのですが、「ざー」という音しか流れ

> せん。
> おそらく録音の段階で問題が発生しているのではないかと思うのですが、問題点を
> 教えていただけないでしょうか。

> --
> このメールは Google グループのグループ「日本Androidの会」の登録者に送られ

> います。
> このグループに投稿するには、android-g...@googlegroups.com にメール

> 送信してください。
> このグループから退会するには、
> android-group-j...@googlegroups.com にメールを送信してくださ

> 。
> 詳細については、http://groups.google.com/group/android-group-japan?hl=ja

> らこのグループにアクセスしてください。
>
>
>

ohisamallc

unread,
Oct 18, 2011, 10:59:52 PM10/18/11
to android-g...@googlegroups.com
山形のohisamaです。

何回も、すいません。
onrecordpositionupdatelistenerを実装してないですね。
自分は、ここまで。


> -----Original Message-----
> From: android-g...@googlegroups.com
> [mailto:android-g...@googlegroups.com]On Behalf Of gaku871
> Sent: Wednesday, October 19, 2011 2:44 AM
> To: 日本Androidの会
> Subject: [work] [android-group-japan: 14824] 録音について
>
>
> 投稿失礼します。
> 現在さまざまなサイトを参考にさせていただきながら録音のできるアプリを作ろう
> としています。
> wav形式のファイルを出力することはできたのですが、「ざー」という音しか流れ

> せん。
> おそらく録音の段階で問題が発生しているのではないかと思うのですが、問題点を
> 教えていただけないでしょうか。
>

Koji Ohno

unread,
Oct 18, 2011, 11:27:19 PM10/18/11
to android-g...@googlegroups.com
こんにちは、大野と申します。

細かく見ていないので間違っていたらすみません。
WAVファイルにするときのエンディアンが逆だったりしませんか?
(私もWAV関係のモノを作るときによく間違えて、ザーッとなるので。。。)


2011年10月19日2:44 gaku871 <gaku8713...@gmail.com>:

トムキャット

unread,
Oct 19, 2011, 2:53:32 AM10/19/11
to 日本Androidの会
トムキャットです。

こういう事例もあります。参考まで。

https://sh-dev.sharp.co.jp/android/modules/d3forum/index.php?topic_id=87


On Oct 19, 12:27 pm, Koji Ohno <s936...@gmail.com> wrote:
> こんにちは、大野と申します。
>
> 細かく見ていないので間違っていたらすみません。
> WAVファイルにするときのエンディアンが逆だったりしませんか?
> (私もWAV関係のモノを作るときによく間違えて、ザーッとなるので。。。)
>
> 2011年10月19日2:44 gaku871 <gaku8713pultn...@gmail.com>:

gaku871

unread,
Oct 19, 2011, 12:15:47 PM10/19/11
to 日本Androidの会
多くのご意見本当にありがとうございます。

上記のプリグラムはraw形式のものも同時に生成されるので、それを既存のフリーソフトでwav形式に変えてもやはり同じでした。
(収録時間が半分になって生成されるのはbit数などの関係でしょうか?)

まだまだプログラム初心者なのでonrecordpositionupdatelistenerの実装について調べてます。

Koji Ohno

unread,
Oct 19, 2011, 5:11:44 PM10/19/11
to android-g...@googlegroups.com
こんにちは、大野と申します。

> フリーソフトでwav形式に変えてもやはり同じでした。

であれば、やっぱりrawとwavのエンディアンの違いだと思います。

rawで ABCDEF..... と格納されているデータを wav では BADCFE.... と
入れ替えて格納しないといけないと思います。

dos.writeShort(bufferRecord[j]);
のところを
int byte1 = bufferRecord[j] & 0xff ;
int byte2 = (bufferRecord[j] >> 8) & 0xff ;
dos.writeByte(byte1) ;
dos.writeByte(byte2) ;
な感じで1バイトずつ、順番を逆にして格納していけば良いと思います。

時間が半分になっているのは、モノラルのデータをステレオとしてWAV化
したのではないでしょうか?

2011年10月20日1:15 gaku871 <gaku8713...@gmail.com>:

gaku871

unread,
Oct 19, 2011, 9:51:45 PM10/19/11
to 日本Androidの会
大野さん

大野さんのおっしゃる問題点で、無事解決することができました。
本当にありがとうございます!!
Reply all
Reply to author
Forward
0 new messages