Android-аудио: изменение высоты тона

Документация Android для SoundPool гласит: "Приложение также может изменять высоту тона, регулируя скорость воспроизведения в реальном времени для доплеровских эффектов или эффектов синтеза". Поэтому я попытался сделать это, используя метод setRate, чтобы плавно варьироваться от одной ноты к другой, но результат ужасен: вариации звука очень рваные. Вот код, который я попробовал. Пожалуйста, скажите мне, если есть лучший способ.

int streamId = soundPool.play (soundId, 1, 1, 1, 0, 1.0f);
for (float x = 0; x < 1; x += 0.005) {
  SystemClock.sleep (10);
  soundPool.setRate (streamId, 1 + x);
}

2 ответа

Несмотря на то, что документация Android предлагает, что вы можете использовать setRate() для получения доплеровских эффектов я бы не стал полагаться на быструю или достаточно хорошую реализацию на каждом устройстве Android.

Доступные аудио ИС требуют фиксированной частоты дискретизации 44 кГц или 48 кГц. Следовательно, преобразование частоты дискретизации (т.е. изменение высоты тона) должно выполняться программно. Поскольку это включает в себя перехват числа на низком уровне, я уверен, что это реализовано производителем устройства, а не Google. Учитывая большое разнообразие производителей устройств Android и часто используемое недорогое оборудование, существует множество реализаций преобразования частоты дискретизации. Некоторые быстрее, некоторые медленнее. Некоторые гладкие, некоторые рваные.

Что происходит при изменении коэффициента конверсии во время воспроизведения? Если алгоритм не совпадает по частям точно, возможно, при воспроизведении звука произошла короткая трещина. Вы меняете коэффициент конверсии каждые 10 миллисекунд. Если каждые 10 мс появляется трещина, это соответствует частоте 100 Гц, которая сама по себе является тоном. Это может быть то, что вы слышите как "рваный".

В общем, я не думаю, что можно эмулировать музыкальные инструменты в режиме реального времени на широком спектре Android-устройств, используя высокоуровневый Android API. Хотя нативное приложение может быть достаточно быстрым.

Попробовав все, я решил использовать SoundPool для изменения высоты тона. При скорости воспроизведения 2,0 звук воспроизводится с частотой, в два раза превышающей исходную, а при скорости воспроизведения 0,5 он воспроизводится с частотой, равной половине его исходной частоты. Диапазон скорости воспроизведения составляет от 0,5 до 2,0. Но он работал с частотой ниже и выше, чем 0,5 и 2,0.

Я публикую свой рабочий код,

но так как это только для демонстрационной цели, здесь вам нужно вручную изменять "скорость воспроизведения", каждый раз, когда вы устанавливаете приложение, например: "sp.play(Explosion, 1,1,0,0,1.5f)" here "1.5f"- скорость воспроизведения. Можно легко создать EditView или что-то подобное, чтобы установить значение скорости воспроизведения во время выполнения.

В этом приложении вам просто нужно нажать на экран приложения, чтобы воспроизвести музыку с установленной скоростью воспроизведения.

import java.io.IOException;

import android.app.Activity;
import android.content.res.AssetFileDescriptor;
import android.media.AudioManager;
import android.media.SoundPool;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class SoundPoolActivity extends Activity implements OnClickListener {

    SoundPool sp;
    int explosion = 0;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

       View v = new View(this);
       v.setOnClickListener(this);
       setContentView(v);
       sp = new SoundPool(1,AudioManager.STREAM_MUSIC,0);
       //explosion = sp.load(this, R.raw.hh,0);
       explosion = sp.load("/sdcard/hh.m4a",0);


    }


    public void onClick(View v){
         if (explosion!=0){

             sp.play(explosion, 1,1,0,0,2.3f);
         }

    }
}
Другие вопросы по тегам