1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/wechart-SoundMeter

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
В этом репозитории не указан файл с открытой лицензией (LICENSE). При использовании обратитесь к конкретному описанию проекта и его зависимостям в коде.
Клонировать/Скачать
README.md 9.2 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
gitlife-traslator Отправлено 29.11.2024 04:19 1d9d3c2

SoundMeter (децибел-метр)

Моя личная страница

Что это?

Подробное описание

Если вам нравится, пожалуйста, поставьте мне звезду

Программа для Android для обнаружения звука в реальном времени, которая получает текущий уровень звукового давления окружающей среды, также известный как значение децибела.

enter image description here

Исходный код

Для сбора звука используется системный 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 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/wechart-SoundMeter.git
git@api.gitlife.ru:oschina-mirror/wechart-SoundMeter.git
oschina-mirror
wechart-SoundMeter
wechart-SoundMeter
master