|
@@ -0,0 +1,229 @@
|
|
|
|
|
+package com.picturegrabbingsystem.audio;
|
|
|
|
|
+
|
|
|
|
|
+import android.content.Context;
|
|
|
|
|
+import android.media.AudioAttributes;
|
|
|
|
|
+import android.media.AudioFormat;
|
|
|
|
|
+import android.media.AudioManager;
|
|
|
|
|
+import android.media.AudioTrack;
|
|
|
|
|
+import android.util.Log;
|
|
|
|
|
+
|
|
|
|
|
+import com.picturegrabbingsystem.global.UdpApplication;
|
|
|
|
|
+import com.picturegrabbingsystem.util.ShellUtils;
|
|
|
|
|
+
|
|
|
|
|
+import java.io.File;
|
|
|
|
|
+import java.io.FileOutputStream;
|
|
|
|
|
+import java.io.IOException;
|
|
|
|
|
+import java.io.InputStream;
|
|
|
|
|
+import java.io.RandomAccessFile;
|
|
|
|
|
+import java.text.DateFormat;
|
|
|
|
|
+import java.text.SimpleDateFormat;
|
|
|
|
|
+import java.util.Calendar;
|
|
|
|
|
+
|
|
|
|
|
+public class AudioCtroller {
|
|
|
|
|
+ private static final String TAG = "AudioCtroller";
|
|
|
|
|
+ private static final String PCM_PATH = "/sdcard/kyne/pcm/high_voltage_voice.pcm";
|
|
|
|
|
+ private static final String ALARM_PCM_PATH = "/sdcard/kyne/pcm/alarm.pcm";
|
|
|
|
|
+
|
|
|
|
|
+ static boolean m_is_playinn = false;
|
|
|
|
|
+
|
|
|
|
|
+ public static void stop(){
|
|
|
|
|
+ Log.i(TAG, "closeGpio 96 scheduly "+m_is_playinn);
|
|
|
|
|
+ m_is_playinn = false;
|
|
|
|
|
+ ShellUtils.closeGpio(96);
|
|
|
|
|
+ }
|
|
|
|
|
+ public static void playAudio() {
|
|
|
|
|
+ Calendar calendar = Calendar.getInstance();
|
|
|
|
|
+ int hour = calendar.get(Calendar.HOUR_OF_DAY);
|
|
|
|
|
+ if(hour > 16 || hour < 6){
|
|
|
|
|
+ Log.i(TAG, "forbidden play void and alarm during rest time ");
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(m_is_playinn){
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ m_is_playinn = true;
|
|
|
|
|
+
|
|
|
|
|
+// if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
|
|
|
|
|
+
|
|
|
|
|
+ AudioAttributes attributes = new AudioAttributes.Builder()
|
|
|
|
|
+ .setUsage(AudioAttributes.USAGE_MEDIA)
|
|
|
|
|
+ .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
|
|
|
|
|
+ .build();
|
|
|
|
|
+ int sampleRateInHz = 44100; // 采样率 ffmpeg -i baojing.mp3 -f s16le -ac 2 -ar 44100 output.pcm
|
|
|
|
|
+ int channelConfig = AudioFormat.CHANNEL_OUT_STEREO;
|
|
|
|
|
+ int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
|
|
|
|
|
+ AudioFormat format = new AudioFormat.Builder()
|
|
|
|
|
+ .setSampleRate(sampleRateInHz)
|
|
|
|
|
+ .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
|
|
|
|
|
+ .setChannelMask(channelConfig)
|
|
|
|
|
+ .build();
|
|
|
|
|
+
|
|
|
|
|
+ int bufferSizeInBytes = AudioTrack.getMinBufferSize(sampleRateInHz, channelConfig, audioFormat); // 缓冲区大小
|
|
|
|
|
+ AudioTrack audioTrack = new AudioTrack(attributes,format,bufferSizeInBytes,AudioTrack.MODE_STREAM, AudioManager.AUDIO_SESSION_ID_GENERATE);
|
|
|
|
|
+
|
|
|
|
|
+// } else {
|
|
|
|
|
+// int streamType = AudioManager.STREAM_MUSIC; // 音频流类型
|
|
|
|
|
+// int sampleRateInHz = 44100; // 采样率
|
|
|
|
|
+// int channelConfig = AudioFormat.CHANNEL_OUT_STEREO; // 声道配置
|
|
|
|
|
+// int audioFormat = AudioFormat.ENCODING_PCM_16BIT; // 音频格式
|
|
|
|
|
+// int bufferSizeInBytes = AudioTrack.getMinBufferSize(sampleRateInHz, channelConfig, audioFormat); // 缓冲区大小
|
|
|
|
|
+// AudioTrack audioTrack = new AudioTrack(streamType, sampleRateInHz, channelConfig, audioFormat, bufferSizeInBytes, AudioTrack.MODE_STREAM);
|
|
|
|
|
+// audioTrack.play();
|
|
|
|
|
+// }
|
|
|
|
|
+
|
|
|
|
|
+ new Thread(() -> {
|
|
|
|
|
+ storePcmInSdcard("high_voltage_voice.pcm",PCM_PATH);
|
|
|
|
|
+ storePcmInSdcard("alarm.pcm",ALARM_PCM_PATH);
|
|
|
|
|
+ RandomAccessFile rafile = null;
|
|
|
|
|
+ RandomAccessFile alarmfile = null;
|
|
|
|
|
+ try {
|
|
|
|
|
+ rafile = new RandomAccessFile(PCM_PATH, "r");
|
|
|
|
|
+ alarmfile = new RandomAccessFile(ALARM_PCM_PATH, "r");
|
|
|
|
|
+ byte[] buffer = new byte[bufferSizeInBytes];
|
|
|
|
|
+ int maxAlarmCount = 2;
|
|
|
|
|
+ int maxVoiceCount = 4;
|
|
|
|
|
+ Log.i(TAG, "openGpio 96 for play audio start");
|
|
|
|
|
+ ShellUtils.openGpio(96);
|
|
|
|
|
+ audioTrack.play();
|
|
|
|
|
+
|
|
|
|
|
+ for(;;){
|
|
|
|
|
+ if(!m_is_playinn){
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ int next = 0;
|
|
|
|
|
+ for(;;) {
|
|
|
|
|
+ if(!m_is_playinn){
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ int read = 0;
|
|
|
|
|
+ while (read != -1) {
|
|
|
|
|
+ if(!m_is_playinn){
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ read = rafile.read(buffer);//fileInputStream.read(buffer);
|
|
|
|
|
+ if (read == AudioTrack.ERROR_BAD_VALUE || read == AudioTrack.ERROR_INVALID_OPERATION) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (read > 0 && audioTrack != null && audioTrack.getPlayState() == AudioTrack.PLAYSTATE_PLAYING && audioTrack.getState() == AudioTrack.STATE_INITIALIZED) {
|
|
|
|
|
+ audioTrack.write(buffer, 0, read);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ next++;
|
|
|
|
|
+ Log.i(TAG, "play voice "+next +" times");
|
|
|
|
|
+ rafile.seek(0);
|
|
|
|
|
+ Thread.sleep(300);
|
|
|
|
|
+ if(next >= maxVoiceCount){
|
|
|
|
|
+ next = 0;
|
|
|
|
|
+ playAlarm(audioTrack,alarmfile,buffer,maxAlarmCount);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ Log.i(TAG, "closeGpio 96 and close all audio files");
|
|
|
|
|
+ ShellUtils.closeGpio(96);
|
|
|
|
|
+ rafile.close();
|
|
|
|
|
+ alarmfile.close();
|
|
|
|
|
+ audioTrack.stop();
|
|
|
|
|
+ audioTrack.release();
|
|
|
|
|
+ } catch (Throwable e) {
|
|
|
|
|
+ Log.i(TAG, "play audio occurs error "+e.getMessage());
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ Log.i(TAG, "closeGpio 96 finally");
|
|
|
|
|
+ ShellUtils.closeGpio(96);
|
|
|
|
|
+ m_is_playinn = false;
|
|
|
|
|
+ try {
|
|
|
|
|
+ if(rafile != null) {
|
|
|
|
|
+ rafile.close();
|
|
|
|
|
+ }
|
|
|
|
|
+ if(alarmfile != null) {
|
|
|
|
|
+ alarmfile.close();
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (IOException e) {
|
|
|
|
|
+ throw new RuntimeException(e);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(audioTrack!= null){
|
|
|
|
|
+ audioTrack.release();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }).start();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private static void playAlarm(AudioTrack audioTrack,RandomAccessFile alarmfile,byte[] buffer, int maxAlarmCount) throws Throwable{
|
|
|
|
|
+ int nextAlarm = 0;
|
|
|
|
|
+ for(;;) {
|
|
|
|
|
+ if(!m_is_playinn){
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ int readAlarm = 0;
|
|
|
|
|
+ while (readAlarm != -1) {
|
|
|
|
|
+ if(!m_is_playinn){
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ readAlarm = alarmfile.read(buffer);//fileInputStream.read(buffer);
|
|
|
|
|
+ if (readAlarm == AudioTrack.ERROR_BAD_VALUE || readAlarm == AudioTrack.ERROR_INVALID_OPERATION) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (readAlarm > 0 && audioTrack != null && audioTrack.getPlayState() == AudioTrack.PLAYSTATE_PLAYING && audioTrack.getState() == AudioTrack.STATE_INITIALIZED) {
|
|
|
|
|
+ audioTrack.write(buffer, 0, readAlarm);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ nextAlarm++;
|
|
|
|
|
+ Log.i(TAG, "play alarm "+nextAlarm +" times");
|
|
|
|
|
+ alarmfile.seek(0);
|
|
|
|
|
+ if(nextAlarm >= maxAlarmCount){
|
|
|
|
|
+ nextAlarm = 0;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+// private void stopPlay() {
|
|
|
|
|
+// if (audioTrack != null) {
|
|
|
|
|
+// audioTrack.release();
|
|
|
|
|
+// }
|
|
|
|
|
+// }
|
|
|
|
|
+
|
|
|
|
|
+ private static void storePcmInSdcard(String assetFileName, String storePath){
|
|
|
|
|
+
|
|
|
|
|
+ InputStream is = null;
|
|
|
|
|
+ FileOutputStream fos =null;
|
|
|
|
|
+ try {
|
|
|
|
|
+ int tail =storePath.lastIndexOf('/');
|
|
|
|
|
+ File dir = new File(storePath.substring(0,tail));
|
|
|
|
|
+ if(!dir.exists()) {
|
|
|
|
|
+ dir.mkdirs();
|
|
|
|
|
+ }
|
|
|
|
|
+ File ff = new File(storePath);
|
|
|
|
|
+ if (!ff.exists()) {
|
|
|
|
|
+ is = UdpApplication.getContext().getAssets().open(assetFileName);
|
|
|
|
|
+// is = context.getAssets().open(assetFileName);
|
|
|
|
|
+ fos = new FileOutputStream(ff);
|
|
|
|
|
+ byte[] buffer = new byte[1024];
|
|
|
|
|
+ int byteCount = 0;
|
|
|
|
|
+ while ((byteCount = is.read(buffer)) != -1) {
|
|
|
|
|
+ fos.write(buffer, 0, byteCount);
|
|
|
|
|
+ }
|
|
|
|
|
+ fos.flush();
|
|
|
|
|
+ is.close();
|
|
|
|
|
+ fos.close();
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (Throwable e) {
|
|
|
|
|
+ e.printStackTrace();
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ if(is!= null){
|
|
|
|
|
+ try {
|
|
|
|
|
+ is.close();
|
|
|
|
|
+ } catch (IOException e) {
|
|
|
|
|
+ throw new RuntimeException(e);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if(fos != null){
|
|
|
|
|
+ try {
|
|
|
|
|
+ fos.close();
|
|
|
|
|
+ } catch (IOException e) {
|
|
|
|
|
+ throw new RuntimeException(e);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+}
|