SoundMeter (децибел-метр)
Программа для Android для обнаружения звука в реальном времени, которая получает текущий уровень звукового давления окружающей среды, также известный как значение децибела.
Для сбора звука используется системный MediaRecorder.
/**
* Запись
* @return Успех начала записи
*/
public boolean startRecorder(){
if (myRecAudioFile == null) {
return false;
}
try {
mMediaRecorder = new MediaRecorder();
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mMediaRecorder.setOutputFile(myRecAudioFile.getAbsolutePath());
mMediaRecorder.prepare();
mMediaRecorder.start();
isRecording = true;
return true;
} catch(IOException exception) {
mMediaRecorder.reset();
mMediaRecorder.release();
mMediaRecorder = null;
isRecording = false ;
exception.printStackTrace();
}catch(IllegalStateException e){
stopRecording();
e.printStackTrace();
isRecording = false ;
}
return false;
}
/**
* Получение значения уровня звукового давления
*/
public float getMaxAmplitude() {
if (mMediaRecorder != null) {
try {
return mMediaRecorder.getMaxAmplitude();
} catch (IllegalArgumentException e) {
e.printStackTrace();
return 0;
}
} else {
return 5;
}
}
Пользовательский вид, отображающий значение уровня звукового давления, называется SoundDiscView.
private float scaleWidth, scaleHeight;
private int newWidth, newHeight;
private Matrix mMatrix = new Matrix();
private Bitmap indicatorBitmap;
private Paint paint = new Paint();
static final long ANIMATION_INTERVAL = 100;
private void init() {
Bitmap myBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.noise_index);
int bitmapWidth = myBitmap.getWidth();
int bitmapHeight = myBitmap.getHeight();
newWidth = getWidth();
newHeight = getHeight();
scaleWidth = ((float) newWidth) /(float) bitmapWidth; // Получить коэффициент масштабирования
scaleHeight = ((float) newHeight) /(float) bitmapHeight; //Получить коэффициент масштабирования
mMatrix.postScale(scaleWidth, scaleHeight); //Установить коэффициент масштабирования mMatrix
indicatorBitmap = Bitmap.createBitmap(myBitmap, 0, 0, bitmapWidth, bitmapHeight, mMatrix,true); //Получить bitmap с указателем того же размера и высоты, что и фон
paint = new Paint();
paint.setTextSize(55);
paint.setAntiAlias(true);
paint.setTextAlign(Paint.Align.CENTER); //Сглаживание
paint.setColor(Color.WHITE);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
currentAngle = getAngle(World.dbCount); //Получить угол, который должен показывать указатель
mMatrix.setRotate(getAngle(World.dbCount), newWidth / 2, newHeight * 215 / 460); //Положение относительно позиции
canvas.drawBitmap(indicatorBitmap, mMatrix, paint);
postInvalidateDelayed(ANIMTATION_INTERVAL);
canvas.drawText((int)World.dbCount+" DB", newWidth/2,newHeight*36/46, paint); //Положение относительно изображения
}
Все операции управления выполняются в MainActivity. При запуске или повторном входе в активность запускается измеритель уровня звукового давления. Код запуска:
@Override
protected void onResume() {
super.onResume();
bListener = true;
File file = FileUtil.createFile("temp.amr"); //Создать файл для записи
if (file != null) {
Log.v("file", "file =" + file.getAbsolutePath());
startRecord(file);
} else {
Toast.makeText(getApplicationContext(), "Ошибка создания файла", Toast.LENGTH_LONG).show();
}
}
/**
* Начать запись
* @param fFile
*/
public void startRecord(File fFile){
try{
mRecorder.setMyRecAudioFile(fFile);
if (mRecorder.startRecorder()) {
startListenAudio();
} else { Toast.makeText(this, "Ошибка запуска записи", Toast.LENGTH_SHORT).show(); } } catch (Exception e) { Toast.makeText(this, «Микрофон уже используется», Toast.LENGTH_SHORT).show(); e.printStackTrace(); }
private void startListenAudio() { thread = new Thread(new Runnable() { @Override public void run() { while (isThreadRun) { try { if (bListener) { volume = mRecorder.getMaxAmplitude(); // Получение значения громкости if (volume > 0 && volume < 1000000) { World.setDbCount(20 * (float)(Math.log10(volume))); // Преобразование значения громкости в децибелы soundDiscView.refresh(); // Обновление представления в фоновом потоке с помощью postInvalidate } } Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); bListener = false; } } } }); thread.start(); }
Процесс выполнения startListenAudio заключается в запуске потока, который каждые несколько секунд получает значение громкости и обновляет представление. При обновлении представления в фоновом потоке необходимо использовать метод postInvalidate. Изучение исходного кода метода postInvalidate показывает, что его принцип работы довольно прост: он использует механизм обработчика, и окончательное обновление происходит в основном потоке.
Когда активность останавливается, необходимо остановить и закрыть процесс записи звука, а затем удалить записанные файлы. Для этого выполняются следующие действия:
Остановка записи @Override protected void onStop() { super.onStop(); bListener = false; mRecorder.delete(); // Остановка записи и удаление файла записи }
public void delete() { stopRecording(); if (myRecAudioFile != null) { myRecAudioFile.delete(); myRecAudioFile = null; } }
Результат:
Эффект в целом хороший, но при перемещении указателя наблюдается слишком резкое движение. Необходимо замедлить скорость перемещения.
public static float dbCount = 40;
private static float lastDbCount = dbCount; private static float min = 0.5f; private static float value = 0; public static void setDbCount(float dbValue) { if (dbValue > lastDbCount) { value = dbValue - lastDbCount > min ? dbValue - lastDbCount : min; } else { value = dbValue - lastDbCount < -min ? dbValue - lastDbCount : -min; } dbCount = lastDbCount + value * 0.2f ; lastDbCount = dbCount; }
После повторного выполнения всё работает идеально!
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )