当前位置: 代码迷 >> Android >> Android话音采集
  详细解决方案

Android话音采集

热度:64   发布时间:2016-05-01 20:49:23.0
Android语音采集

Android端的语音采集主要是调用AudioRecord,首先说几个参数

?

private static AudioRecord mRecord;	// 音频获取源	private int audioSource = MediaRecorder.AudioSource.MIC;	// 设置音频采样率,44100是目前的标准,但是某些设备仍然支持22050,16000,11025	private static int sampleRateInHz = 8000;// 44100;	// 设置音频的录制的声道CHANNEL_IN_STEREO为双声道,CHANNEL_CONFIGURATION_MONO为单声道	private static int channelConfig = AudioFormat.CHANNEL_CONFIGURATION_MONO;// AudioFormat.CHANNEL_IN_STEREO;	// 音频数据格式:PCM 16位每个样本。保证设备支持。PCM 8位每个样本。不一定能得到设备支持。	private static int audioFormat = AudioFormat.ENCODING_PCM_16BIT;	// 音频大小	private int bufSize;

?然后初始化一下AudioRecord,过程如下:

?

?

bufSize = AudioRecord.getMinBufferSize(sampleRateInHz, channelConfig,				audioFormat);		mRecord = new AudioRecord(audioSource, sampleRateInHz, channelConfig,				audioFormat, bufSize);

?初始化完毕以后就需要采集音频数据了:

?

mRecord.startRecording();		short audiodata[] = new short[bufSize];		while (isRecord) {			int readsize = 0;			while (isRecord == true) {				readsize = mRecord.read(audiodata, 0, bufSize);				try {					for (int i = 0; i < readsize; i++) {						//dout.writeShort(audiodata[i]);                                              //数据处理					}				} catch (IOException e) {					// TODO Auto-generated catch block					e.printStackTrace();				}			}		}		mRecord.stop();		audiodata = null;

?接下来是一个语音的播放了,我们这边不放的是采集到的语音流,即PCM无损格式的语音数据,如下:

参数:

?

	private static AudioTrack mTrack;	// 音频类型	private int streamType = AudioManager.STREAM_MUSIC;	// 设置音频采样率,44100是目前的标准,但是某些设备仍然支持22050,16000,11025	private int sampleRateInHz = 8000;// 44100;	// 设置音频的录制的声道CHANNEL_IN_STEREO为双声道,CHANNEL_CONFIGURATION_MONO为单声道	private int channelConfig = AudioFormat.CHANNEL_CONFIGURATION_MONO;// AudioFormat.CHANNEL_IN_STEREO;	// 音频数据格式:PCM 16位每个样本。保证设备支持。PCM 8位每个样本。不一定能得到设备支持。	private int audioFormat = AudioFormat.ENCODING_PCM_16BIT;	// 音频大小	private int bufSize;	// 音频模式	private int mode = AudioTrack.MODE_STREAM;	protected boolean keepRuning = true;

?然后初始化播放器:

?

bufSize = AudioTrack.getMinBufferSize(sampleRateInHz, channelConfig,				audioFormat);		mTrack = new AudioTrack(streamType, sampleRateInHz, channelConfig,				audioFormat, bufSize, mode);

?然后是播放:

?

DataOutputStream dos = null;		mTrack.play();		try {			revSocket = server.accept();			dos = new DataOutputStream(new BufferedOutputStream(					new FileOutputStream(audioFile)));			din = new DataInputStream(revSocket.getInputStream());		} catch (IOException e) {			// TODO Auto-generated catch block			e.printStackTrace();		}		while (keepRuning) {			short[] buffer = new short[bufSize / 4];			try {				Log.i("状态", "接收数据");				for (int i = 0; din.available() > 0 && i < buffer.length; i++) {					buffer[i] = din.readShort();					dos.writeShort(buffer[i]);					Log.i("状态", "接收数据," + String.valueOf(i));				}				short[] bytes_pkg = buffer.clone();				mTrack.write(bytes_pkg, 0, bytes_pkg.length);			} catch (Exception e) {				e.printStackTrace();			}		}		mTrack.stop();		try {			dos.close();			din.close();		} catch (IOException e) {			// TODO Auto-generated catch block			e.printStackTrace();		}	}
将语音数据保存到文件,并且将裸数据文件保存成可播放的WAV文件
/**	 * 这里将数据写入文件,但是并不能播放,因为AudioRecord获得的音频是原始的裸音频,	 * 如果需要播放就必须加入一些格式或者编码的头信息。但是这样的好处就是你可以对音频的 裸数据进行处理,比如你要做一个爱说话的TOM	 * 猫在这里就进行音频的处理,然后重新封装 所以说这样得到的音频比较容易做一些音频的处理。	 */	private void writeDateTOFile() {		// new一个byte数组用来存一些字节数据,大小为缓冲区大小		byte[] audiodata = new byte[minBufSize];		FileOutputStream fos = null;		int readsize = 0;		try {			File file = new File(AudioName);			if (file.exists()) {				file.delete();			}			fos = new FileOutputStream(file);// 建立一个可存取字节的文件		} catch (Exception e) {			e.printStackTrace();		}		while (isRecord == true) {			readsize = mRecord.read(audiodata, 0, minBufSize);			Log.i("采集大小", String.valueOf(readsize));			if (AudioRecord.ERROR_INVALID_OPERATION != readsize) {				try {					fos.write(audiodata);				} catch (IOException e) {					e.printStackTrace();				}			}		}		try {			fos.close();// 关闭写入流		} catch (IOException e) {			e.printStackTrace();		}	}	// 这里得到可播放的音频文件	private void copyWaveFile(String inFilename, String outFilename) {		FileInputStream in = null;		FileOutputStream out = null;		long totalAudioLen = 0;		long totalDataLen = totalAudioLen + 36;		long longSampleRate = sampleRateInHz;		int channels = 2;		long byteRate = 16 * sampleRateInHz * channels / 8;		byte[] data = new byte[minBufSize];		try {			in = new FileInputStream(inFilename);			out = new FileOutputStream(outFilename);			totalAudioLen = in.getChannel().size();			totalDataLen = totalAudioLen + 36;			WriteWaveFileHeader(out, totalAudioLen, totalDataLen,					longSampleRate, channels, byteRate);			while (in.read(data) != -1) {				out.write(data);			}			in.close();			out.close();		} catch (FileNotFoundException e) {			e.printStackTrace();		} catch (IOException e) {			e.printStackTrace();		}	}	/**	 * 这里提供一个头信息。插入这些信息就可以得到可以播放的文件。 为我为啥插入这44个字节,这个还真没深入研究,不过你随便打开一个wav	 * 音频的文件,可以发现前面的头文件可以说基本一样哦。每种格式的文件都有 自己特有的头文件。	 */	private void WriteWaveFileHeader(FileOutputStream out, long totalAudioLen,			long totalDataLen, long longSampleRate, int channels, long byteRate)			throws IOException {		byte[] header = new byte[44];		header[0] = 'R'; // RIFF/WAVE header		header[1] = 'I';		header[2] = 'F';		header[3] = 'F';		header[4] = (byte) (totalDataLen & 0xff);		header[5] = (byte) ((totalDataLen >> 8) & 0xff);		header[6] = (byte) ((totalDataLen >> 16) & 0xff);		header[7] = (byte) ((totalDataLen >> 24) & 0xff);		header[8] = 'W';		header[9] = 'A';		header[10] = 'V';		header[11] = 'E';		header[12] = 'f'; // 'fmt ' chunk		header[13] = 'm';		header[14] = 't';		header[15] = ' ';		header[16] = 16; // 4 bytes: size of 'fmt ' chunk		header[17] = 0;		header[18] = 0;		header[19] = 0;		header[20] = 1; // format = 1		header[21] = 0;		header[22] = (byte) channels;		header[23] = 0;		header[24] = (byte) (longSampleRate & 0xff);		header[25] = (byte) ((longSampleRate >> 8) & 0xff);		header[26] = (byte) ((longSampleRate >> 16) & 0xff);		header[27] = (byte) ((longSampleRate >> 24) & 0xff);		header[28] = (byte) (byteRate & 0xff);		header[29] = (byte) ((byteRate >> 8) & 0xff);		header[30] = (byte) ((byteRate >> 16) & 0xff);		header[31] = (byte) ((byteRate >> 24) & 0xff);		header[32] = (byte) (2 * 16 / 8); // block align		header[33] = 0;		header[34] = 16; // bits per sample		header[35] = 0;		header[36] = 'd';		header[37] = 'a';		header[38] = 't';		header[39] = 'a';		header[40] = (byte) (totalAudioLen & 0xff);		header[41] = (byte) ((totalAudioLen >> 8) & 0xff);		header[42] = (byte) ((totalAudioLen >> 16) & 0xff);		header[43] = (byte) ((totalAudioLen >> 24) & 0xff);		out.write(header, 0, 44);	}
?播放裸语音数据文件
short[] buffer = new short[bufferSize / 4];			try {				// 定义输入流,将音频写入到AudioTrack类中,实现播放				DataInputStream dis = new DataInputStream(						new BufferedInputStream(new FileInputStream(audioFile)));				// 实例AudioTrack				AudioTrack track = new AudioTrack(AudioManager.STREAM_MUSIC,						frequence, channelConfig, audioEncoding, bufferSize,						AudioTrack.MODE_STREAM);				// 开始播放				track.play();				// 由于AudioTrack播放的是流,所以,我们需要一边播放一边读取				while (isPlaying && dis.available() > 0) {					int i = 0;					while (dis.available() > 0 && i < buffer.length) {						buffer[i] = dis.readShort();						i++;					}					// 然后将数据写入到AudioTrack中					track.write(buffer, 0, buffer.length);				}				// 播放结束				track.stop();				dis.close();			} catch (Exception e) {				// TODO: handle exception			}
?
  相关解决方案