Intereting Posts
Холст не обновляется (недействителен) до тех пор, пока весь цикл не кончится Удалить тень под панелью действий Должны ли вызовы в Content Resolver выполняться в Сервисе (т. Е. Отдельный поток)? Невозможно вызвать getSupportFragmentManager () из действия Как я могу получить недавно используемые контакты в android? Перезагрузка Android-сервиса, когда приложение убито Сделать нижний экран в полноэкранном режиме над строкой состояния Android-градир, собственные библиотеки для разных архитектур Невозможно сгенерировать подписанный APK с proguard, включенным при использовании Joda Time Android google maps async задает добавить маркеры CreateBitmap – java.lang.IllegalArgumentException: x должно быть <bitmap.width () Руководство по GPS-навигатору Удалить значок заголовка группы по умолчанию расширенного списка DevicePolicyManager.lockNow (); Не отключает экран, если для параметров безопасности задано значение Слайд / Нет Проблема с аутентификацией в устройстве BLE Bluetooth Low Energy

Получите частоту аудиофайла через каждые 1/4 секунды в android

У меня есть звуковой файл (.3gp) и его около ~ 1 мин. Я хотел бы получить частоту этого звукового файла каждые 1/4 секунды. Моя идея состоит в том, чтобы получать образцы в каждые 1/4 секунды из аудиофайла, а с помощью FFT я могу получить значения частоты. Есть какой-либо способ сделать это?

На самом деле я бы разбил звуковой файл на 1 / 4sec образцы звуковых файлов (alwyas, переписывая превью), затем используя алгоритм FFT и обнаруживая частоту, где magintude является самым большим. Но могут быть более легкие решения, однако я также не знаю, как это сделать.

*** ОБНОВЛЕНИЕ 2 – новый код

Я использую этот код:

public class RecordAudio extends AsyncTask<Void, double[], Void> { @Override protected Void doInBackground(Void... arg0) { try { int bufferSize = AudioRecord.getMinBufferSize(frequency, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT); //int bufferSize = AudioRecord.getMinBufferSize(frequency, // channelConfiguration, audioEncoding); AudioRecord audioRecord = new AudioRecord( MediaRecorder.AudioSource.MIC, frequency, channelConfiguration, audioEncoding, bufferSize); short[] buffer = new short[blockSize]; //double[] toTransform = new double[blockSize]; audioRecord.startRecording(); // started = true; hopes this should true before calling // following while loop while (started) { sampling++; double[] re = new double[blockSize]; double[] im = new double[blockSize]; double[] newArray = new double[blockSize*2]; double[] magns = new double[blockSize]; double MaxMagn=0; double pitch = 0; int bufferReadResult = audioRecord.read(buffer, 0, blockSize); for (int i = 0; i < blockSize && i < bufferReadResult; i++) { re[i] = (double) buffer[i] / 32768.0; // signed 16bit im[i] = 0; } newArray = FFTbase.fft(re, im,true); for (int i = 0; i < newArray.length; i+=2) { re[i/2]=newArray[i]; im[i/2]=newArray[i+1]; magns[i/2] = Math.sqrt(re[i/2]*re[i/2]+im[i/2]*im[i/2]); } // I only need the first half for (int i = 0; i < (magns.length)/2; i++) { if (magns[i]>MaxMagn) { MaxMagn = magns[i]; pitch=i; } } if (sampling > 50) { Log.i("pitch and magnitude", "" + MaxMagn + " " + pitch*15.625f); sampling=0; MaxMagn=0;pitch=0; } } audioRecord.stop(); } catch (Throwable t) { t.printStackTrace(); Log.e("AudioRecord", "Recording Failed"); } return null; } 

Я использую это: http://www.wikijava.org/wiki/The_Fast_Fourier_Transform_in_Java_%28part_1%29

Гитарные струны кажутся правильными, но мой собственный звук не хорош из-за этого:

Введите описание изображения здесь

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

Прослеживание высоты тона с помощью FFT задается так часто в Stack Overflow. Я написал запись в блоге с образцом кода . Код находится на C, но с объяснениями и ссылками вы сможете делать то, что хотите.

Что касается деления его на 1/4 секунды, вы можете просто взять БПФ из 1/4 вторых сегментов, как вы предложили, вместо дефолта (который, я думаю, составляет около 1 секунды). Если это не дает вам частотного разрешения, вам, возможно, придется использовать другой метод распознавания тона. Другое, что вы можете сделать, это использовать перекрывающиеся сегменты длиной более 1/4 секунды, но начинать с интервалов, которые на 1/4 секунды друг от друга. Этот метод упоминается в блоге, но он может не соответствовать вашей спецификации дизайна.

Попробуйте AsyncTask :

 class GetFrequency extends AsyncTask<String, Void, Void> { public Void doInBackground(String... params) { while (true) { // Apply Logic Here try { Thread.sleep(250); } catch (Exception ie) { // TODO Auto-generated catch block e.printStackTrace(); } } } } 

Назовите это в своем MainActivity,

 frequencyButtonListener.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { new GetFrequency.execute(params); } });