Java 在智能手机上播放通过蓝牙从SensorTile(STEVAL-STLKT01V1)接收的音频
我正在制作一个应用程序,可以播放通过蓝牙从带有传感器(包括麦克风)的电路板接收到的音频。 在音频功能的“活动”中有两个按钮,允许您以流模式开始播放音频并停止播放。不幸的是,目前它不能像我所希望的那样工作。 问题是audioSample是空的,所以我无法进入onUpdate方法并从样本中提取音频 更改:侦听器更改,添加一个按钮以禁用音频 以下是与活动相关的代码:Java 在智能手机上播放通过蓝牙从SensorTile(STEVAL-STLKT01V1)接收的音频,java,android,bluetooth,audio-streaming,stm32,Java,Android,Bluetooth,Audio Streaming,Stm32,我正在制作一个应用程序,可以播放通过蓝牙从带有传感器(包括麦克风)的电路板接收到的音频。 在音频功能的“活动”中有两个按钮,允许您以流模式开始播放音频并停止播放。不幸的是,目前它不能像我所希望的那样工作。 问题是audioSample是空的,所以我无法进入onUpdate方法并从样本中提取音频 更改:侦听器更改,添加一个按钮以禁用音频 以下是与活动相关的代码: package com.st.BlueSTSDK.Example; import android.content.Context; i
package com.st.BlueSTSDK.Example;
import android.content.Context;
import android.content.Intent;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.SeekBar;
import com.st.BlueSTSDK.Feature;
import com.st.BlueSTSDK.Features.FeatureAudioADPCM;
import com.st.BlueSTSDK.Features.FeatureAudioADPCMSync;
import com.st.BlueSTSDK.Manager;
import com.st.BlueSTSDK.Node;
import com.st.BlueSTSDK.Utils.BVAudioSyncManager;
import java.util.List;
/**
* Created by Cesare on 09/06/2017.
*/
public class FeatureAudioActivity extends AppCompatActivity {
/**
* Node that will show the data
*/
private Node mNode;
/** fragment used for keep the connection open */
private NodeContainerFragment mNodeContainer;
// Feature on which to apply the listener
private FeatureAudioADPCM mAudio;
// feature where we read the audio sync values
private FeatureAudioADPCMSync mAudioSync;
// The sampling rate
private static final int SAMPLE_RATE = 8000;
// raw audio
private short audioSample[];
// audio manager
private static final int AUDIO_STREAM = AudioManager.STREAM_MUSIC;
// Audio track builder
private AudioTrack mAudioTrack;
//object containing the sync data needed in a ADPCM stream decoding
private BVAudioSyncManager mBVAudioSyncManager = new BVAudioSyncManager();
private final static String NODE_FRAGMENT = FeatureAudioActivity.class.getCanonicalName() + "" +
".NODE_FRAGMENT";
private final static String NODE_TAG = FeatureAudioActivity.class.getCanonicalName() + "" +
".NODE_TAG";
/**
* create an intent for start the activity that will log the information from the node
*
* @param c context used for create the intent
* @param node note that will be used by the activity
* @return intent for start this activity
*/
public static Intent getStartIntent(Context c, @NonNull Node node) {
Intent i = new Intent(c, FeatureAudioActivity.class);
i.putExtra(NODE_TAG, node.getTag());
i.putExtras(NodeContainerFragment.prepareArguments(node));
return i;
}
/**
* listener for the audio feature, it will updates the audio values
*/
public final Feature.FeatureListener mAudioListener = new Feature.FeatureListener() {
@Override
public void onUpdate(final Feature f, final Feature.Sample sample) {
audioSample = FeatureAudioADPCM.getAudio(sample);
}
};
/**
* listener for the audioSync feature, it will update the synchronism values
*/
public final Feature.FeatureListener mAudioSyncListener = new Feature.FeatureListener() {
@Override
public void onUpdate(Feature f, final Feature.Sample sample) {
if(mBVAudioSyncManager!=null){
mBVAudioSyncManager.setSyncParams(sample);
}
}
};
/* ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// */
private SeekBar mVolumeBar;
private AudioManager mAudioManager;
private Button mPlayButton;
private Button mStopButton;
private ImageButton mMuteButton;
private boolean mIsMute = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_feature_audio);
// find the node.
String nodeTag = getIntent().getStringExtra(NODE_TAG);
mNode = Manager.getSharedInstance().getNodeWithTag(nodeTag);
List<Feature> listFeature = mNode.getFeatures();
for (Feature f : listFeature) {
if (f.isEnabled() && f.getName().equals("AudioFeature")) {
mAudio=(FeatureAudioADPCM) f;
}//if
if (f.isEnabled() && f.getName().equals("AudioSyncFeature")) {
mAudioSync=(FeatureAudioADPCMSync) f;
}//if
}//for
//create/recover the NodeContainerFragment
if (savedInstanceState == null) {
Intent i = getIntent();
mNodeContainer = new NodeContainerFragment();
mNodeContainer.setArguments(i.getExtras());
getFragmentManager().beginTransaction()
.add(mNodeContainer, NODE_FRAGMENT).commit();
} else {
mNodeContainer = (NodeContainerFragment) getFragmentManager()
.findFragmentByTag(NODE_FRAGMENT);
}//if-else
//builder audio track
mAudioTrack = new AudioTrack(
AudioManager.STREAM_MUSIC,
SAMPLE_RATE,
AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT,
FeatureAudioADPCM.AUDIO_PACKAGE_SIZE,
AudioTrack.MODE_STREAM);
mPlayButton = (Button) findViewById(R.id.playButton);
mStopButton = (Button) findViewById(R.id.stopButton);
mMuteButton = (ImageButton) findViewById(R.id.muteButton);
// //start speaker phone
// AudioManager audioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
// audioManager.setMode(AudioManager.MODE_IN_CALL);
// audioManager.setSpeakerphoneOn(true);
// When the play button is pressed
mPlayButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mAudioTrack.play();
/*Write audio data for playback
@param short : The array that contains the data for playback
@param int: offset in rawAudio where playback data begins
@param int: The number of shorts to read in rawAudio after the offset
*/
mAudioTrack.write(audioSample,0,audioSample.length);
}
});
//When the stop button is pressed
mStopButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mAudioTrack.stop();
}
});
//When the mute button is pressed
mMuteButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
changeState();
}
boolean changeState(){
mIsMute=!mIsMute;
if(mIsMute)
muteAudio();
else
unMuteAudio();
return mIsMute;
}
private void muteAudio(){
mMuteButton.setImageResource(R.drawable.ic_volume_off_black_32dp);
mAudioManager.setStreamVolume(AUDIO_STREAM,0,0);
mVolumeBar.setEnabled(false);
}
private void unMuteAudio(){
mMuteButton.setImageResource(R.drawable.ic_volume_up_black_32dp);
mAudioManager.setStreamVolume(AUDIO_STREAM,mVolumeBar.getProgress(),0);
mVolumeBar.setEnabled(true);
}
});
setVolumeControlStream(AudioManager.STREAM_MUSIC);
initControls();
mAudioSync.addFeatureListener(mAudioSyncListener);
mAudio.setAudioSyncManager(mBVAudioSyncManager);
mAudio.addFeatureListener(mAudioListener);
mNode.enableNotification(mAudio);
}
// Volume control from SeekBar
private void initControls()
{
try
{
mVolumeBar = (SeekBar)findViewById(R.id.volumeValue);
mAudioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
mVolumeBar.setMax(mAudioManager
.getStreamMaxVolume(AudioManager.STREAM_MUSIC));
mVolumeBar.setProgress(mAudioManager
.getStreamVolume(AudioManager.STREAM_MUSIC));
mVolumeBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener()
{
@Override
public void onStopTrackingTouch(SeekBar arg0)
{
}
@Override
public void onStartTrackingTouch(SeekBar arg0)
{
}
@Override
public void onProgressChanged(SeekBar arg0, int progress, boolean arg2)
{
mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC,
progress, 0);
}
});
}
catch (Exception e)
{
e.printStackTrace();
}
}
/**
* if we have to leave this activity, we force to keep the connection open, since we go back
* in the {@link FeatureListActivity}
*/
@Override
public void onBackPressed() {
mNodeContainer.keepConnectionOpen(true);
super.onBackPressed();
}//onBackPressed
}
package com.st.BlueSTSDK.Example;
导入android.content.Context;
导入android.content.Intent;
导入android.media.AudioFormat;
导入android.media.AudioManager;
导入android.media.AudioTrack;
导入android.os.Bundle;
导入android.support.annotation.NonNull;
导入android.support.v7.app.AppActivity;
导入android.view.view;
导入android.widget.Button;
导入android.widget.ImageButton;
导入android.widget.SeekBar;
导入com.st.BlueSTSDK.Feature;
导入com.st.BlueSTSDK.Features.FeatureAudioADPCM;
导入com.st.BlueSTSDK.Features.FeatureAudioADPCMSync;
导入com.st.BlueSTSDK.Manager;
导入com.st.BlueSTSDK.Node;
导入com.st.BlueSTSDK.Utils.BVAudioSyncManager;
导入java.util.List;
/**
*由Cesare于2017年6月9日创建。
*/
公共类功能AudioActivity扩展了AppCompatActivity{
/**
*将显示数据的节点
*/
私有节点mNode;
/**用于保持连接打开的片段*/
私有节点容器片段mNodeContainer;
//应用侦听器的功能
私人特辑Adpcm mAudio;
//我们读取音频同步值的功能
专用功能AudioADPCMSync mAudioSync;
//抽样率
私有静态最终整数抽样率=8000;
//原始音频
私人短音频样本[];
//音频管理器
私有静态最终int AUDIO\u STREAM=AudioManager.STREAM\u MUSIC;
//音轨生成器
私人音轨;
//对象,该对象包含ADPCM流解码所需的同步数据
私有BVAudioSyncManager mBVAudioSyncManager=新BVAudioSyncManager();
私有最终静态字符串节点_FRAGMENT=FeatureAudioActivity.class.getCanonicalName()+“”+
“.NODE_片段”;
私有最终静态字符串节点_TAG=FeatureAudioActivity.class.getCanonicalName()+“”+
“.NODE_标记”;
/**
*创建启动活动的意图,该活动将记录来自节点的信息
*
*@param c上下文用于创建意图
*@param节点注释将由活动使用
*@返回开始此活动的意图
*/
公共静态意图GetStartEnt(上下文c,@NonNull节点){
意图i=新意图(c,FeatureAudioActivity.class);
i、 putExtra(NODE_标记,NODE.getTag());
i、 putExtras(NodeContainerFragment.prepareArguments(node));
返回i;
}
/**
*侦听器对于音频功能,它将更新音频值
*/
public final Feature.FeatureListener MaudoListener=新功能。FeatureListener(){
@凌驾
公共void onUpdate(最终特征f,最终特征.示例){
audioSample=FeatureAudioADPCM.getAudio(示例);
}
};
/**
*对于audioSync功能的侦听器,它将更新同步值
*/
public final Feature.FeatureListener mAudioSyncListener=新功能。FeatureListener(){
@凌驾
公共void onUpdate(功能f,最终功能。示例){
if(mBVAudioSyncManager!=null){
mBVAudioSyncManager.setSyncParams(示例);
}
}
};
/* ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// */
私人SeekBar mVolumeBar;
私人音频经理;
私人按钮;
私人按钮mStopButton;
私有图像按钮mmutebuton;
私有布尔mIsMute=false;
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity\u feature\u audio);
//找到节点。
字符串nodeTag=getIntent().getStringExtra(节点标记);
mNode=Manager.getSharedInstance().getNodeWithTag(nodeTag);
List listFeature=mNode.getFeatures();
用于(功能f:listFeature){
如果(f.isEnabled()&&f.getName().equals(“AudioFeature”)){
mAudio=(FeatureAudioADPCM)f;
}//如果
如果(f.isEnabled()&&f.getName().equals(“AudioSyncFeature”)){
mAudioSync=(FeatureAudioADPCMSync)f;
}//如果
}//为了
//创建/恢复NodeContainerFragment
如果(savedInstanceState==null){
Intent i=getIntent();
mNodeContainer=new NodeContainerFragment();
setArguments(i.getExtras());
getFragmentManager().beginTransaction()
.add(mNodeContainer,节点_片段).commit();
}否则{
mNodeContainer=(NodeContainerFragment)getFragmentManager()
.findFragmentByTag(节点\片段);
}//否则
//建设者音轨
mAudioTrack=新的音频曲目(
AudioManager.STREAM_音乐,
抽样率,
AudioFormat.CHANNEL\u OUT\u MONO,
AudioFormat.ENCODING_PCM_16位,
功能AudioADPCM.AUDIO\u包装尺寸,
音频跟踪模式(音频流);
mPlayButton=(按钮)findviewbyd(R.id.playButton);
mStopButton=(按钮)findviewbyd(R.id.stopButton);
mMuteButton=(ImageButton)findViewById(R.id.muteButton);
////启动扬声器电话
//音频管理器音频管理
package com.st.BlueSTSDK.Example;
import android.content.Context;
import android.content.Intent;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.SeekBar;
import com.st.BlueSTSDK.Feature;
import com.st.BlueSTSDK.Features.FeatureAudioADPCM;
import com.st.BlueSTSDK.Features.FeatureAudioADPCMSync;
import com.st.BlueSTSDK.Manager;
import com.st.BlueSTSDK.Node;
import com.st.BlueSTSDK.Utils.BVAudioSyncManager;
import java.util.List;
public class FeatureAudioActivity extends AppCompatActivity {
/**
* Node that will show the data
*/
private Node mNode;
/** fragment used for keep the connection open */
private NodeContainerFragment mNodeContainer;
// Feature on which to apply the listener
private FeatureAudioADPCM mAudio;
// feature where we read the audio sync values
private FeatureAudioADPCMSync mAudioSync;
// The sampling rate
private static final int SAMPLE_RATE = 8000;
// audio manager
private static final int AUDIO_STREAM = AudioManager.STREAM_MUSIC;
// Audio track builder
private AudioTrack mAudioTrack;
//object containing the sync data needed in a ADPCM stream decoding
private BVAudioSyncManager mBVAudioSyncManager = new BVAudioSyncManager();
private final static String NODE_FRAGMENT = FeatureAudioActivity.class.getCanonicalName() + "" +
".NODE_FRAGMENT";
private final static String NODE_TAG = FeatureAudioActivity.class.getCanonicalName() + "" +
".NODE_TAG";
/**
* create an intent for start the activity that will log the information from the node
*
* @param c context used for create the intent
* @param node note that will be used by the activity
* @return intent for start this activity
*/
public static Intent getStartIntent(Context c, @NonNull Node node) {
Intent i = new Intent(c, FeatureAudioActivity.class);
i.putExtra(NODE_TAG, node.getTag());
i.putExtras(NodeContainerFragment.prepareArguments(node));
return i;
}
/**
* listener for the audio feature, it will updates the audio values
*/
public final Feature.FeatureListener mAudioListener = new Feature.FeatureListener() {
@Override
public void onUpdate(final Feature f, final Feature.Sample sample) {
short audioSample[] = FeatureAudioADPCM.getAudio(sample);
/*Write audio data for playback
@param short : The array that contains the data for playback
@param int: offset in rawAudio where playback data begins
@param int: The number of shorts to read in rawAudio after the offset
*/
mAudioTrack.write(audioSample,0,audioSample.length);
}
};
/**
* listener for the audioSync feature, it will update the synchronism values
*/
public final Feature.FeatureListener mAudioSyncListener = new Feature.FeatureListener() {
@Override
public void onUpdate(Feature f, final Feature.Sample sample) {
if(mBVAudioSyncManager!=null){
mBVAudioSyncManager.setSyncParams(sample);
}
}
};
/* ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// */
private SeekBar mVolumeBar;
private AudioManager mAudioManager;
private Button mPlayButton;
private Button mStopButton;
private ImageButton mMuteButton;
private boolean mIsMute = false;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_feature_audio);
// find the node.
String nodeTag = getIntent().getStringExtra(NODE_TAG);
mNode = Manager.getSharedInstance().getNodeWithTag(nodeTag);
List<Feature> listFeature = mNode.getFeatures();
for (Feature f : listFeature) {
if (f.isEnabled() && f.getName().equals("AudioFeature")) {
mAudio=(FeatureAudioADPCM) f;
}//if
if (f.isEnabled() && f.getName().equals("AudioSyncFeature")) {
mAudioSync=(FeatureAudioADPCMSync) f;
}//if
}//for
//create/recover the NodeContainerFragment
if (savedInstanceState == null) {
Intent i = getIntent();
mNodeContainer = new NodeContainerFragment();
mNodeContainer.setArguments(i.getExtras());
getFragmentManager().beginTransaction()
.add(mNodeContainer, NODE_FRAGMENT).commit();
} else {
mNodeContainer = (NodeContainerFragment) getFragmentManager()
.findFragmentByTag(NODE_FRAGMENT);
}//if-else
//builder audio track
mAudioTrack = new AudioTrack(
AudioManager.STREAM_MUSIC,
SAMPLE_RATE,
AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT,
FeatureAudioADPCM.AUDIO_PACKAGE_SIZE,
AudioTrack.MODE_STREAM);
mPlayButton = (Button) findViewById(R.id.playButton);
mStopButton = (Button) findViewById(R.id.stopButton);
mMuteButton = (ImageButton) findViewById(R.id.muteButton);
// When the play button is pressed
mPlayButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(!mIsMute){
mAudioTrack.play();
mAudioManager.setStreamVolume(AUDIO_STREAM,mVolumeBar.getProgress(),0);
}
}
});
//When the stop button is pressed
mStopButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
stopAudioTrack();
mAudioManager.setStreamVolume(AUDIO_STREAM,0,0);
}
});
//When the mute button is pressed
mMuteButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
changeState();
}
boolean changeState(){
mIsMute=!mIsMute;
if(mIsMute)
muteAudio();
else
unMuteAudio();
return mIsMute;
}
private void muteAudio(){
mMuteButton.setImageResource(R.drawable.ic_volume_off_black_32dp);
mAudioManager.setStreamVolume(AUDIO_STREAM,0,0);
mVolumeBar.setEnabled(false);
}
private void unMuteAudio(){
mMuteButton.setImageResource(R.drawable.ic_volume_up_black_32dp);
mAudioManager.setStreamVolume(AUDIO_STREAM,mVolumeBar.getProgress(),0);
mVolumeBar.setEnabled(true);
}
});
//enable control volume
setVolumeControlStream(AudioManager.STREAM_MUSIC);
initControls();
}
@Override
public void onResume(){
super.onResume();
// enable needed notification
if(mAudio!=null && mAudioSync!=null) {
mAudio.addFeatureListener(mAudioListener);
mBVAudioSyncManager.reinitResetFlag();
mAudio.setAudioSyncManager(mBVAudioSyncManager);
mNode.enableNotification(mAudio);
mAudioSync.addFeatureListener(mAudioSyncListener);
mNode.enableNotification(mAudioSync);
}
}
@Override
public void onPause(){
super.onPause();
// disable needed notification
if(mAudio!=null) {
mAudio.removeFeatureListener(mAudioListener);
mNode.disableNotification(mAudio);
}
if(mAudioSync!=null) {
mAudioSync.removeFeatureListener(mAudioSyncListener);
mNode.disableNotification(mAudioSync);
}
}
private void stopAudioTrack(){
synchronized(this) {
mAudioTrack.pause();
mAudioTrack.flush();
}
}
// Volume control from SeekBar
private void initControls()
{
try
{
mVolumeBar = (SeekBar)findViewById(R.id.volumeValue);
mAudioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
mVolumeBar.setMax(mAudioManager
.getStreamMaxVolume(AudioManager.STREAM_MUSIC));
mVolumeBar.setProgress(mAudioManager
.getStreamVolume(AudioManager.STREAM_MUSIC));
mVolumeBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener()
{
@Override
public void onStopTrackingTouch(SeekBar arg0)
{
}
@Override
public void onStartTrackingTouch(SeekBar arg0)
{
}
@Override
public void onProgressChanged(SeekBar arg0, int progress, boolean arg2)
{
mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC,
progress, 0);
}
});
}
catch (Exception e)
{
e.printStackTrace();
}
}
/**
* if we have to leave this activity, we force to keep the connection open, since we go back
* in the {@link FeatureListActivity}
*/
@Override
public void onBackPressed() {
mNodeContainer.keepConnectionOpen(true);
super.onBackPressed();
}//onBackPressed