Intereting Posts
Логика для использования нескольких веб-просмотров в TabLayout для решения проблемы памяти Прослушивать нажатие и перетаскивание значения и функции соответственно Android: программно определить, есть ли у устройства аппаратное меню Android Gradle запускает тесты на не-отладочные сборки Изменить стиль ProgressDialog Относительно расположенные элементы в прокручиваемом абсолютно позиционированном div «отстают» от прокрутки Java.lang.RuntimeException: невозможно создать обработчик внутри потока, который не вызвал Looper.prepare (); Android: изменение цвета фона фрагмента Фрагменты остаются после того, как активность Get убита и воссоздана Android Maven Не удалось найти инструмент 'aapt' Горизонтальный линейный градиент с android Ошибка DexFile.class в eclipse SimpleCursorTreeAdapter и CursorLoader для ExpandableListView Ошибка тестирования тестовой программы для Android Studio: пустой тестовый комплект Как добавить строку в нижней части счетчика, как, например, edittext в android

Android: Как изменить скорость воспроизведения музыки с помощью OpenSL ES

Я работаю над музыкальным проигрывателем, в котором мне нужно изменить темп (скорость воспроизведения музыки) без изменения высоты тона.

Я не могу найти какой-либо родной класс для Android. Я пробовал SoundPool, но он не работает с большими музыкальными файлами, и он также не работает на многих устройствах. Я также попробовал AudioTrack, но опять не повезло.

Теперь я пытаюсь использовать пример Android NDK, который использует OpenSL ES для обработки музыки. Теперь я просто хочу добавить функцию набора скорости воспроизведения в этом примере.

Может ли кто-нибудь показать мне, как мне добавить функцию изменения скорости воспроизведения?

Solutions Collecting From Web of "Android: Как изменить скорость воспроизведения музыки с помощью OpenSL ES"

Я решил свою проблему. Вот мой полный собственный код для OpenSL ES, если кому-то это нужно:

#include <jni.h> #include<android/log.h> // LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog 넣어주세요 #define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, "OSLESMediaPlayer", __VA_ARGS__) #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG , "OSLESMediaPlayer", __VA_ARGS__) #define LOGI(...) __android_log_print(ANDROID_LOG_INFO , "OSLESMediaPlayer", __VA_ARGS__) #define LOGW(...) __android_log_print(ANDROID_LOG_WARN , "OSLESMediaPlayer", __VA_ARGS__) #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR , "OSLESMediaPlayer", __VA_ARGS__) // for native audio #include <SLES/OpenSLES.h> #include <SLES/OpenSLES_Android.h> #include <assert.h> #include <sys/types.h> // engine interfaces static SLObjectItf engineObject = NULL; static SLEngineItf engineEngine; // URI player interfaces static SLObjectItf uriPlayerObject = NULL; static SLPlayItf uriPlayerPlay; static SLSeekItf uriPlayerSeek; static SLPlaybackRateItf uriPlaybackRate; // output mix interfaces static SLObjectItf outputMixObject = NULL; // playback rate (default 1x:1000) static SLpermille playbackMinRate = 500; static SLpermille playbackMaxRate = 2000; static SLpermille playbackRateStepSize; //Pitch static SLPitchItf uriPlaybackPitch; static SLpermille playbackMinPitch = 500; static SLpermille playbackMaxPitch = 2000; // create the engine and output mix objects JNIEXPORT void Java_com_swssm_waveloop_audio_OSLESMediaPlayer_createEngine( JNIEnv* env, jclass clazz) { SLresult result; // create engine LOGD("create engine"); result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL); assert(SL_RESULT_SUCCESS == result); // realize the engine LOGD("realize the engine"); result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE); assert(SL_RESULT_SUCCESS == result); // get the engine interface, which is needed in order to create other objects LOGD("get the engine interface"); result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine); assert(SL_RESULT_SUCCESS == result); // create output mix, with environmental reverb specified as a non-required interface LOGD("create output mix"); const SLInterfaceID ids[1] = {SL_IID_PLAYBACKRATE}; const SLboolean req[1] = {SL_BOOLEAN_FALSE}; result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 1, ids, req); assert(SL_RESULT_SUCCESS == result); // realize the output mix LOGD("realize the output mix"); result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE); assert(SL_RESULT_SUCCESS == result); } JNIEXPORT void Java_com_swssm_waveloop_audio_OSLESMediaPlayer_releaseEngine( JNIEnv* env, jclass clazz) { // destroy URI audio player object, and invalidate all associated interfaces if (uriPlayerObject != NULL) { (*uriPlayerObject)->Destroy(uriPlayerObject); uriPlayerObject = NULL; uriPlayerPlay = NULL; uriPlayerSeek = NULL; } // destroy output mix object, and invalidate all associated interfaces if (outputMixObject != NULL) { (*outputMixObject)->Destroy(outputMixObject); outputMixObject = NULL; } // destroy engine object, and invalidate all associated interfaces if (engineObject != NULL) { (*engineObject)->Destroy(engineObject); engineObject = NULL; engineEngine = NULL; } } /* void OnCompletion(JNIEnv* env, jclass clazz) { jclass cls = env->GetObjectClass(thiz); if (cls != NULL) { jmethodID mid = env->GetMethodID(cls, "OnCompletion", "()V"); if (mid != NULL) { env->CallVoidMethod(thiz, mid, 1234); } } }*/ void playStatusCallback(SLPlayItf play, void* context, SLuint32 event) { //LOGD("playStatusCallback"); } // create URI audio player JNIEXPORT jboolean Java_com_swssm_waveloop_audio_OSLESMediaPlayer_createAudioPlayer( JNIEnv* env, jclass clazz, jstring uri) { SLresult result; // convert Java string to UTF-8 const jbyte *utf8 = (*env)->GetStringUTFChars(env, uri, NULL); assert(NULL != utf8); // configure audio source // (requires the INTERNET permission depending on the uri parameter) SLDataLocator_URI loc_uri = { SL_DATALOCATOR_URI, (SLchar *) utf8 }; SLDataFormat_MIME format_mime = { SL_DATAFORMAT_MIME, NULL, SL_CONTAINERTYPE_UNSPECIFIED }; SLDataSource audioSrc = { &loc_uri, &format_mime }; // configure audio sink SLDataLocator_OutputMix loc_outmix = { SL_DATALOCATOR_OUTPUTMIX, outputMixObject }; SLDataSink audioSnk = { &loc_outmix, NULL }; // create audio player const SLInterfaceID ids[2] = { SL_IID_SEEK, SL_IID_PLAYBACKRATE }; const SLboolean req[2] = { SL_BOOLEAN_FALSE, SL_BOOLEAN_TRUE }; result = (*engineEngine)->CreateAudioPlayer(engineEngine, &uriPlayerObject, &audioSrc, &audioSnk, 2, ids, req); // note that an invalid URI is not detected here, but during prepare/prefetch on Android, // or possibly during Realize on other platforms assert(SL_RESULT_SUCCESS == result); // release the Java string and UTF-8 (*env)->ReleaseStringUTFChars(env, uri, utf8); // realize the player result = (*uriPlayerObject)->Realize(uriPlayerObject, SL_BOOLEAN_FALSE); // this will always succeed on Android, but we check result for portability to other platforms if (SL_RESULT_SUCCESS != result) { (*uriPlayerObject)->Destroy(uriPlayerObject); uriPlayerObject = NULL; return JNI_FALSE; } // get the play interface result = (*uriPlayerObject)->GetInterface(uriPlayerObject, SL_IID_PLAY, &uriPlayerPlay); assert(SL_RESULT_SUCCESS == result); // get the seek interface result = (*uriPlayerObject)->GetInterface(uriPlayerObject, SL_IID_SEEK, &uriPlayerSeek); assert(SL_RESULT_SUCCESS == result); // get playback rate interface result = (*uriPlayerObject)->GetInterface(uriPlayerObject, SL_IID_PLAYBACKRATE, &uriPlaybackRate); assert(SL_RESULT_SUCCESS == result); /* // get playback pitch interface result = (*uriPlayerObject)->GetInterface(uriPlayerObject, SL_IID_PITCH, &uriPlaybackPitch); assert(SL_RESULT_SUCCESS == result);*/ // register callback function result = (*uriPlayerPlay)->RegisterCallback(uriPlayerPlay, playStatusCallback, 0); assert(SL_RESULT_SUCCESS == result); result = (*uriPlayerPlay)->SetCallbackEventsMask(uriPlayerPlay, SL_PLAYEVENT_HEADATEND); // head at end assert(SL_RESULT_SUCCESS == result); SLmillisecond msec; result = (*uriPlayerPlay)->GetDuration(uriPlayerPlay, &msec); assert(SL_RESULT_SUCCESS == result); // no loop result = (*uriPlayerSeek)->SetLoop(uriPlayerSeek, SL_BOOLEAN_TRUE, 0, msec); assert(SL_RESULT_SUCCESS == result); SLuint32 capa; result = (*uriPlaybackRate)->GetRateRange(uriPlaybackRate, 0, &playbackMinRate, &playbackMaxRate, &playbackRateStepSize, &capa); assert(SL_RESULT_SUCCESS == result); result = (*uriPlaybackRate)->SetPropertyConstraints(uriPlaybackRate, SL_RATEPROP_PITCHCORAUDIO); if (SL_RESULT_PARAMETER_INVALID == result) { LOGD("Parameter Invalid"); } if (SL_RESULT_FEATURE_UNSUPPORTED == result) { LOGD("Feature Unsupported"); } if (SL_RESULT_SUCCESS == result) { assert(SL_RESULT_SUCCESS == result); LOGD("Success"); } /* result = (*uriPlaybackPitch)->GetPitchCapabilities(uriPlaybackPitch, &playbackMinPitch, &playbackMaxPitch); assert(SL_RESULT_SUCCESS == result);*/ /* SLpermille minRate, maxRate, stepSize, rate = 1000; SLuint32 capa; (*uriPlaybackRate)->GetRateRange(uriPlaybackRate, 0, &minRate, &maxRate, &stepSize, &capa); (*uriPlaybackRate)->SetRate(uriPlaybackRate, minRate); */ return JNI_TRUE; } JNIEXPORT void Java_com_swssm_waveloop_audio_OSLESMediaPlayer_releaseAudioPlayer( JNIEnv* env, jclass clazz) { // destroy URI audio player object, and invalidate all associated interfaces if (uriPlayerObject != NULL) { (*uriPlayerObject)->Destroy(uriPlayerObject); uriPlayerObject = NULL; uriPlayerPlay = NULL; uriPlayerSeek = NULL; uriPlaybackRate = NULL; } } void setPlayState(SLuint32 state) { SLresult result; // make sure the URI audio player was created if (NULL != uriPlayerPlay) { // set the player's state result = (*uriPlayerPlay)->SetPlayState(uriPlayerPlay, state); assert(SL_RESULT_SUCCESS == result); } } SLuint32 getPlayState() { SLresult result; // make sure the URI audio player was created if (NULL != uriPlayerPlay) { SLuint32 state; result = (*uriPlayerPlay)->GetPlayState(uriPlayerPlay, &state); assert(SL_RESULT_SUCCESS == result); return state; } return 0; } // play JNIEXPORT void Java_com_swssm_waveloop_audio_OSLESMediaPlayer_play(JNIEnv* env, jclass clazz) { setPlayState(SL_PLAYSTATE_PLAYING); } // stop JNIEXPORT void Java_com_swssm_waveloop_audio_OSLESMediaPlayer_stop(JNIEnv* env, jclass clazz) { setPlayState(SL_PLAYSTATE_STOPPED); } // pause JNIEXPORT void Java_com_swssm_waveloop_audio_OSLESMediaPlayer_pause(JNIEnv* env, jclass clazz) { setPlayState(SL_PLAYSTATE_PAUSED); } // pause JNIEXPORT jboolean Java_com_swssm_waveloop_audio_OSLESMediaPlayer_isPlaying( JNIEnv* env, jclass clazz) { return (getPlayState() == SL_PLAYSTATE_PLAYING); } // set position JNIEXPORT void Java_com_swssm_waveloop_audio_OSLESMediaPlayer_seekTo( JNIEnv* env, jclass clazz, jint position) { if (NULL != uriPlayerPlay) { //SLuint32 state = getPlayState(); //setPlayState(SL_PLAYSTATE_PAUSED); SLresult result; result = (*uriPlayerSeek)->SetPosition(uriPlayerSeek, position, SL_SEEKMODE_FAST); assert(SL_RESULT_SUCCESS == result); //setPlayState(state); } } // get duration JNIEXPORT jint Java_com_swssm_waveloop_audio_OSLESMediaPlayer_getDuration( JNIEnv* env, jclass clazz) { if (NULL != uriPlayerPlay) { SLresult result; SLmillisecond msec; result = (*uriPlayerPlay)->GetDuration(uriPlayerPlay, &msec); assert(SL_RESULT_SUCCESS == result); return msec; } return 0.0f; } // get current position JNIEXPORT jint Java_com_swssm_waveloop_audio_OSLESMediaPlayer_getPosition( JNIEnv* env, jclass clazz) { if (NULL != uriPlayerPlay) { SLresult result; SLmillisecond msec; result = (*uriPlayerPlay)->GetPosition(uriPlayerPlay, &msec); assert(SL_RESULT_SUCCESS == result); return msec; } return 0.0f; } //llllllllllllllllllll JNIEXPORT void Java_com_swssm_waveloop_audio_OSLESMediaPlayer_setPitch( JNIEnv* env, jclass clazz, jint rate) { if (NULL != uriPlaybackPitch) { SLresult result; result = (*uriPlaybackPitch)->SetPitch(uriPlaybackPitch, rate); assert(SL_RESULT_SUCCESS == result); } } JNIEXPORT void Java_com_swssm_waveloop_audio_OSLESMediaPlayer_setRate( JNIEnv* env, jclass clazz, jint rate) { if (NULL != uriPlaybackRate) { SLresult result; result = (*uriPlaybackRate)->SetRate(uriPlaybackRate, rate); assert(SL_RESULT_SUCCESS == result); } } JNIEXPORT jint Java_com_swssm_waveloop_audio_OSLESMediaPlayer_getRate( JNIEnv* env, jclass clazz) { if (NULL != uriPlaybackRate) { SLresult result; SLpermille rate; result = (*uriPlaybackRate)->GetRate(uriPlaybackRate, &rate); assert(SL_RESULT_SUCCESS == result); return rate; } return 0; } // create URI audio player JNIEXPORT jboolean Java_com_swssm_waveloop_audio_OSLESMediaPlayer_setLoop( JNIEnv* env, jclass clazz, jint startPos, jint endPos) { SLresult result; result = (*uriPlayerSeek)->SetLoop(uriPlayerSeek, SL_BOOLEAN_TRUE, startPos, endPos); assert(SL_RESULT_SUCCESS == result); return JNI_TRUE; } // create URI audio player JNIEXPORT jboolean Java_com_swssm_waveloop_audio_OSLESMediaPlayer_setNoLoop( JNIEnv* env, jclass clazz) { SLresult result; if (NULL != uriPlayerSeek) { // enable whole file looping result = (*uriPlayerSeek)->SetLoop(uriPlayerSeek, SL_BOOLEAN_TRUE, 0, SL_TIME_UNKNOWN); assert(SL_RESULT_SUCCESS == result); } return JNI_TRUE; } 

Просто скомпилируйте его с помощью команды ndk-build и используйте его. Если кто-то получит успех в изменении тональности, то, пожалуйста, скажите мне решение.

Вот файл android.mk

 LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := audio-tools LOCAL_SRC_FILES := OSLESMediaPlayer.c LOCAL_CFLAGS := -DHAVE_CONFIG_H -DFPM_ARM -ffast-math -O3 LOCAL_LDLIBS += -lOpenSLES -llog include $(BUILD_SHARED_LIBRARY) 

И файл Application.mk

 APP_STL := gnustl_static APP_CPPFLAGS += -fexceptions -frtti APP_ABI := armeabi armeabi-v7a 

И класс-оболочка, вы можете использовать его функцию непосредственно в своем проекте

 package com.swssm.waveloop.audio; public class OSLESMediaPlayer { public native void createEngine(); public native void releaseEngine(); public native boolean createAudioPlayer(String uri); public native void releaseAudioPlayer(); public native void play(); public native void stop(); public native void pause(); public native boolean isPlaying(); public native void seekTo(int position); public native int getDuration(); public native int getPosition(); public native void setPitch(int rate); public native void setRate(int rate); public native int getRate(); public native void setLoop( int startPos, int endPos ); public native void setNoLoop(); public interface OnCompletionListener { public void OnCompletion(); } private OnCompletionListener mCompletionListener; public void SetOnCompletionListener( OnCompletionListener listener ) { mCompletionListener = listener; } private void OnCompletion() { mCompletionListener.OnCompletion(); int position = getPosition(); int duration = getDuration(); if( position != duration ) { int a = 0; } else { int c = 0; } } } 

Это может оказать некоторую помощь (взято из документации NDK OpenSL):

Скорость воспроизведения

Поддерживаемые диапазоны (и) скорости воспроизведения могут варьироваться в зависимости от версии и реализации платформы и поэтому должны определяться во время выполнения путем запросов с помощью PlaybackRate :: GetRateRange или PlaybackRate :: GetCapabilitiesOfRate.

Тем не менее, некоторые рекомендации по типичным диапазонам ставок могут быть полезными: в Android 2.3 поддерживается типичная поддержка скорости воспроизведения от 500 до 1000 в миллион включительно, а свойство SL_RATEPROP_NOPITCHCORAUDIO. В Android 4.0 такой же диапазон скоростей обычно поддерживается для источника данных в формате PCM, а также для диапазона единиц измерения для других форматов.