当前位置: 首页 > wzjs >正文

展会网站建设sem工作原理

展会网站建设,sem工作原理,网站建设的建议和意见,福州网站建设索q479185700一、完整项目结构 app/ ├── src/ │ ├── main/ │ │ ├── java/com/example/audioplayer/ │ │ │ ├── AudioPlayer.java │ │ │ └── MainActivity.java │ │ ├── cpp/ │ │ │ ├── opensl_player.h │ │ │ ├…

一、完整项目结构

app/
├── src/
│   ├── main/
│   │   ├── java/com/example/audioplayer/
│   │   │   ├── AudioPlayer.java
│   │   │   └── MainActivity.java
│   │   ├── cpp/
│   │   │   ├── opensl_player.h
│   │   │   ├── opensl_player.cpp
│   │   │   └── native-lib.cpp
│   │   └── CMakeLists.txt

二、完整Java层实现

2.1 AudioPlayer.java

package com.example.audioplayer;public class AudioPlayer {public interface PlaybackListener {void onPlaybackStarted();void onPlaybackStopped();void onPlaybackError(String message);}static {System.loadLibrary("audioplayer");}private long nativeHandle;private PlaybackListener listener;public AudioPlayer() {nativeHandle = nativeCreate();}public void setPlaybackListener(PlaybackListener listener) {this.listener = listener;}public void start(String filePath) {if (nativeHandle != 0) {nativeStart(nativeHandle, filePath);}}public void stop() {if (nativeHandle != 0) {nativeStop(nativeHandle);}}public void release() {if (nativeHandle != 0) {nativeRelease(nativeHandle);nativeHandle = 0;}}// Native方法private native long nativeCreate();private native void nativeRelease(long handle);private native void nativeStart(long handle, String filePath);private native void nativeStop(long handle);// 供Native层调用的回调方法private void onPlaybackStarted() {if (listener != null) {listener.onPlaybackStarted();}}private void onPlaybackStopped() {if (listener != null) {listener.onPlaybackStopped();}}private void onError(String message) {if (listener != null) {listener.onPlaybackError(message);}}
}

三、完整Native层实现

3.1 opensl_player.h

#ifndef OPENSL_PLAYER_H
#define OPENSL_PLAYER_H#include <SLES/OpenSLES.h>
#include <SLES/OpenSLES_Android.h>
#include <atomic>
#include <mutex>
#include <vector>class OpenSLPlayer {
public:enum PlayerState {IDLE,PLAYING,PAUSED};OpenSLPlayer();~OpenSLPlayer();bool init(int sampleRate, int channelCount, int bufferSize);void start();void stop();void pause();void resume();void release();bool enqueueData(const void* data, size_t size);PlayerState getState() const { return state.load(); }// 回调接口void setPlaybackCallback(void (*startCallback)(void*),void (*stopCallback)(void*),void (*errorCallback)(const char*, void*),void* context);private:// OpenSL ES对象SLObjectItf engineObj;SLEngineItf engine;SLObjectItf outputMixObj;SLObjectItf playerObj;SLPlayItf playerPlay;SLAndroidSimpleBufferQueueItf playerBufferQueue;// 状态管理std::atomic<PlayerState> state{IDLE};bool initialized = false;std::mutex stateMutex;// 回调相关void (*startCallback)(void*) = nullptr;void (*stopCallback)(void*) = nullptr;void (*errorCallback)(const char*, void*) = nullptr;void* callbackContext = nullptr;// 初始化方法bool createEngine();bool createOutputMix();bool createPlayer(int sampleRate, int channelCount);void destroyPlayer();// 静态回调函数static void bufferQueueCallback(SLAndroidSimpleBufferQueueItf bq, void* context);
};#endif // OPENSL_PLAYER_H

3.2 opensl_player.cpp

#include "opensl_player.h"
#include <cassert>
#include <cstring>
#include <unistd.h>OpenSLPlayer::OpenSLPlayer() : engineObj(nullptr), engine(nullptr),outputMixObj(nullptr), playerObj(nullptr),playerPlay(nullptr), playerBufferQueue(nullptr) {}OpenSLPlayer::~OpenSLPlayer() {release();
}bool OpenSLPlayer::init(int sampleRate, int channelCount, int bufferSize) {std::lock_guard<std::mutex> lock(stateMutex);if (initialized) {return true;}if (!createEngine()) {return false;}if (!createOutputMix()) {release();return false;}if (!createPlayer(sampleRate, channelCount)) {release();return false;}initialized = true;return true;
}bool OpenSLPlayer::createEngine() {const SLInterfaceID engine_ids[] = {SL_IID_ENGINE};const SLboolean engine_req[] = {SL_BOOLEAN_TRUE};SLresult result = slCreateEngine(&engineObj, 0, nullptr, 0, engine_ids, engine_req);if (result != SL_RESULT_SUCCESS) {return false;}result = (*engineObj)->Realize(engineObj, SL_BOOLEAN_FALSE);if (result != SL_RESULT_SUCCESS) {return false;}result = (*engineObj)->GetInterface(engineObj, SL_IID_ENGINE, &engine);return result == SL_RESULT_SUCCESS;
}bool OpenSLPlayer::createOutputMix() {const SLInterfaceID ids[] = {SL_IID_ENVIRONMENTALREVERB};const SLboolean req[] = {SL_BOOLEAN_FALSE};SLresult result = (*engine)->CreateOutputMix(engine, &outputMixObj, 1, ids, req);if (result != SL_RESULT_SUCCESS) {return false;}result = (*outputMixObj)->Realize(outputMixObj, SL_BOOLEAN_FALSE);return result == SL_RESULT_SUCCESS;
}bool OpenSLPlayer::createPlayer(int sampleRate, int channelCount) {// 配置音频源SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE,2 // 双缓冲};SLDataFormat_PCM format_pcm = {SL_DATAFORMAT_PCM,static_cast<SLuint32>(channelCount),static_cast<SLuint32>(sampleRate * 1000), // 转换为毫赫兹SL_PCMSAMPLEFORMAT_FIXED_16,SL_PCMSAMPLEFORMAT_FIXED_16,channelCount == 2 ? (SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT) : SL_SPEAKER_FRONT_CENTER,SL_BYTEORDER_LITTLEENDIAN};SLDataSource audioSrc = {&loc_bufq, &format_pcm};// 配置音频输出SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX,outputMixObj};SLDataSink audioSnk = {&loc_outmix, nullptr};// 创建播放器const SLInterfaceID player_ids[] = {SL_IID_BUFFERQUEUE, SL_IID_VOLUME};const SLboolean player_req[] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};SLresult result = (*engine)->CreateAudioPlayer(engine, &playerObj, &audioSrc, &audioSnk,sizeof(player_ids)/sizeof(player_ids[0]), player_ids, player_req);if (result != SL_RESULT_SUCCESS) {return false;}result = (*playerObj)->Realize(playerObj, SL_BOOLEAN_FALSE);if (result != SL_RESULT_SUCCESS) {return false;}result = (*playerObj)->GetInterface(playerObj, SL_IID_PLAY, &playerPlay);if (result != SL_RESULT_SUCCESS) {return false;}result = (*playerObj)->GetInterface(playerObj, SL_IID_BUFFERQUEUE, &playerBufferQueue);if (result != SL_RESULT_SUCCESS) {return false;}// 注册回调result = (*playerBufferQueue)->RegisterCallback(playerBufferQueue, bufferQueueCallback, this);return result == SL_RESULT_SUCCESS;
}void OpenSLPlayer::bufferQueueCallback(SLAndroidSimpleBufferQueueItf bq, void* context) {OpenSLPlayer* player = static_cast<OpenSLPlayer*>(context);// 这里可以添加缓冲区处理逻辑
}void OpenSLPlayer::start() {if (!initialized) return;std::lock_guard<std::mutex> lock(stateMutex);if (state == IDLE || state == PAUSED) {SLresult result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PLAYING);if (result == SL_RESULT_SUCCESS) {state = PLAYING;if (startCallback) {startCallback(callbackContext);}} else if (errorCallback) {errorCallback("Failed to start playback", callbackContext);}}
}void OpenSLPlayer::stop() {if (!initialized) return;std::lock_guard<std::mutex> lock(stateMutex);if (state != IDLE) {SLresult result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_STOPPED);if (result == SL_RESULT_SUCCESS) {state = IDLE;if (stopCallback) {stopCallback(callbackContext);}} else if (errorCallback) {errorCallback("Failed to stop playback", callbackContext);}}
}bool OpenSLPlayer::enqueueData(const void* data, size_t size) {if (!initialized || state != PLAYING) {return false;}SLresult result = (*playerBufferQueue)->Enqueue(playerBufferQueue, data, size);if (result != SL_RESULT_SUCCESS) {if (errorCallback) {errorCallback("Failed to enqueue audio data", callbackContext);}return false;}return true;
}void OpenSLPlayer::release() {std::lock_guard<std::mutex> lock(stateMutex);if (playerObj != nullptr) {(*playerObj)->Destroy(playerObj);playerObj = nullptr;playerPlay = nullptr;playerBufferQueue = nullptr;}if (outputMixObj != nullptr) {(*outputMixObj)->Destroy(outputMixObj);outputMixObj = nullptr;}if (engineObj != nullptr) {(*engineObj)->Destroy(engineObj);engineObj = nullptr;engine = nullptr;}initialized = false;state = IDLE;
}

3.3 native-lib.cpp (JNI层)

#include <jni.h>
#include <string>
#include "opensl_player.h"struct JavaCallbackContext {JavaVM* jvm;jobject javaPlayer;jmethodID startMethod;jmethodID stopMethod;jmethodID errorMethod;
};void playbackStartCallback(void* context) {JavaCallbackContext* ctx = static_cast<JavaCallbackContext*>(context);JNIEnv* env;ctx->jvm->AttachCurrentThread(&env, nullptr);env->CallVoidMethod(ctx->javaPlayer, ctx->startMethod);ctx->jvm->DetachCurrentThread();
}void playbackStopCallback(void* context) {JavaCallbackContext* ctx = static_cast<JavaCallbackContext*>(context);JNIEnv* env;ctx->jvm->AttachCurrentThread(&env, nullptr);env->CallVoidMethod(ctx->javaPlayer, ctx->stopMethod);ctx->jvm->DetachCurrentThread();
}void playbackErrorCallback(const char* message, void* context) {JavaCallbackContext* ctx = static_cast<JavaCallbackContext*>(context);JNIEnv* env;ctx->jvm->AttachCurrentThread(&env, nullptr);jstring jMessage = env->NewStringUTF(message);env->CallVoidMethod(ctx->javaPlayer, ctx->errorMethod, jMessage);env->DeleteLocalRef(jMessage);ctx->jvm->DetachCurrentThread();
}extern "C" JNIEXPORT jlong JNICALL
Java_com_example_audioplayer_AudioPlayer_nativeCreate(JNIEnv* env, jobject instance) {OpenSLPlayer* player = new OpenSLPlayer();// 设置Java回调JavaCallbackContext* context = new JavaCallbackContext();env->GetJavaVM(&context->jvm);context->javaPlayer = env->NewGlobalRef(instance);jclass clazz = env->GetObjectClass(instance);context->startMethod = env->GetMethodID(clazz, "onPlaybackStarted", "()V");context->stopMethod = env->GetMethodID(clazz, "onPlaybackStopped", "()V");context->errorMethod = env->GetMethodID(clazz, "onError", "(Ljava/lang/String;)V");player->setPlaybackCallback(playbackStartCallback,playbackStopCallback,playbackErrorCallback,context);return reinterpret_cast<jlong>(player);
}extern "C" JNIEXPORT void JNICALL
Java_com_example_audioplayer_AudioPlayer_nativeRelease(JNIEnv* env, jobject instance, jlong handle) {OpenSLPlayer* player = reinterpret_cast<OpenSLPlayer*>(handle);if (player) {JavaCallbackContext* context = static_cast<JavaCallbackContext*>(player->getCallbackContext());if (context) {env->DeleteGlobalRef(context->javaPlayer);delete context;}delete player;}
}extern "C" JNIEXPORT void JNICALL
Java_com_example_audioplayer_AudioPlayer_nativeStart(JNIEnv* env, jobject instance, jlong handle, jstring filePath) {OpenSLPlayer* player = reinterpret_cast<OpenSLPlayer*>(handle);if (player) {const char* path = env->GetStringUTFChars(filePath, nullptr);// 初始化播放器 (44100Hz, 立体声, 4096字节缓冲区)if (!player->init(44100, 2, 4096)) {env->ReleaseStringUTFChars(filePath, path);return;}// 这里应该添加从文件读取音频数据的逻辑// 简单示例: 直接开始播放player->start();env->ReleaseStringUTFChars(filePath, path);}
}extern "C" JNIEXPORT void JNICALL
Java_com_example_audioplayer_AudioPlayer_nativeStop(JNIEnv* env, jobject instance, jlong handle) {OpenSLPlayer* player = reinterpret_cast<OpenSLPlayer*>(handle);if (player) {player->stop();}
}

四、CMakeLists.txt配置

cmake_minimum_required(VERSION 3.4.1)# 设置编译选项
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -Wall -Wextra")# 查找OpenSL ES库
find_library(OPENSLES_LIB OpenSLES)# 添加native库
add_library(audioplayerSHAREDsrc/main/cpp/native-lib.cppsrc/main/cpp/opensl_player.cppsrc/main/cpp/opensl_player.h
)# 链接库
target_link_libraries(audioplayer${OPENSLES_LIB}androidlog
)# 包含目录
include_directories(src/main/cpp)

五、使用示例

5.1 MainActivity.java

package com.example.audioplayer;import android.os.Bundle;
import android.widget.Button;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;public class MainActivity extends AppCompatActivity {private AudioPlayer audioPlayer;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);audioPlayer = new AudioPlayer();audioPlayer.setPlaybackListener(new AudioPlayer.PlaybackListener() {@Overridepublic void onPlaybackStarted() {runOnUiThread(() -> Toast.makeText(MainActivity.this, "播放开始", Toast.LENGTH_SHORT).show());}@Overridepublic void onPlaybackStopped() {runOnUiThread(() -> Toast.makeText(MainActivity.this, "播放停止", Toast.LENGTH_SHORT).show());}@Overridepublic void onPlaybackError(String message) {runOnUiThread(() -> Toast.makeText(MainActivity.this, "错误: " + message, Toast.LENGTH_LONG).show());}});Button playButton = findViewById(R.id.play_button);playButton.setOnClickListener(v -> {String audioPath = "你的音频文件路径";audioPlayer.start(audioPath);});Button stopButton = findViewById(R.id.stop_button);stopButton.setOnClickListener(v -> audioPlayer.stop());}@Overrideprotected void onDestroy() {super.onDestroy();audioPlayer.release();}
}

六、实现说明

  1. ​初始化流程​​:

    • 创建OpenSL ES引擎
    • 创建输出混音器
    • 创建音频播放器
    • 设置缓冲区队列回调
  2. ​播放控制​​:

    • start(): 开始播放
    • stop(): 停止播放
    • pause()/resume(): 暂停/恢复播放
  3. ​数据管理​​:

    • enqueueData(): 向缓冲区队列添加音频数据
    • 缓冲区队列回调处理
  4. ​线程安全​​:

    • 使用std::mutex保护关键状态
    • 使用std::atomic保证状态变量的原子性
  5. ​内存管理​​:

    • release()中正确释放所有OpenSL ES资源
    • 在JNI层管理Java对象的全局引用

这个完整实现提供了从Java层到Native层的完整音频播放解决方案,开发者可以直接集成到项目中,或者根据需要进行修改扩展。

http://www.dtcms.com/wzjs/150590.html

相关文章:

  • 哪里有好的免费的网站建设台州seo快速排名
  • 品牌型网站建设哪家百度账号登录个人中心
  • wordpress删除导入xml如何对seo进行优化
  • 怎么用iapp做网站软件seo站内优化包括
  • 网站改版原因今天的三个新闻
  • 单位内部网站建设优化大师电脑版下载
  • django网站开发案例如何成为百度广告代理商
  • 做彩票网站需要境外手机怎么做网站免费的
  • 大连公司企业网站建设搜外网
  • 网站建设与推广实训小结手机网站优化排名
  • php动态网站开发软件广州百度竞价开户
  • 阿芹网站建设网络推广seo怎么做
  • 西宁市建设网站公司重大新闻事件
  • 吉首网站建设百度浏览器官网下载并安装
  • 推广网站wap端怎么做磁力岛引擎
  • 使用session和cookie实现网站自动登录 .net如何设计一个网站页面
  • 付网站开发费计入什么科目南京谷歌seo
  • 网站建设架构竞价广告是什么意思
  • 网站建设模板制作是什么意思nba最快的绝杀
  • 建网站公司西安的网络优化公司
  • 做宣传海报网站网址提交入口
  • 网站怎么快速做排名百度广告推广电话
  • 做添加剂的外贸网站有哪些最新清远发布
  • 闵行虹桥网站建设百度官网首页下载
  • 软件工程三要素优化网站链接的方法
  • 做淘宝要用到哪些网站宿迁网站建设制作
  • 青海省建设网站企业北京seo执行
  • 北京南昌网站建设免费生成短链接
  • 装饰网站卧室做炕百度顾问式营销
  • 苹果电脑做网站设计做seo需要投入的成本