J2ME/Blackberry - 获取音频信号幅度级别?
Posted
技术标签:
【中文标题】J2ME/Blackberry - 获取音频信号幅度级别?【英文标题】:J2ME/Blackberry - get audio signal amplitude level? 【发布时间】:2009-09-30 12:05:03 【问题描述】:在 j2me 中是否可以测量 JSR-135 播放器制作的音频记录的信号幅度? 我知道我可以访问缓冲区,但是然后呢?
目标型号 Bold 9000,支持格式 PCM 和 AMR。我应该使用哪种格式?
另请参阅 Blackberry Audio Recording Sample CodeHow To - Record Audio on a BlackBerry smartphone
谢谢!
【问题讨论】:
【参考方案1】:获取原始 PCM 信号电平
使用菜单和拨轮在图形内放大/缩小和左/右移动。 音频格式:原始 8000 Hz 16 位单声道 pcm。 在 Bold 9000 RIM OS 4.6 上测试 算法应该适用于任何支持 j2me 和 pcm 的移动设备,当然实现可能需要更改。使用线程进行录音:
class VoiceNotesRecorderThread extends Thread
private Player _player;
private RecordControl _rcontrol;
private ByteArrayOutputStream _output;
private byte _data[];
VoiceNotesRecorderThread()
public void run()
try
_player = Manager
.createPlayer("capture://audio?encoding=audio/basic");
_player.realize();
_rcontrol = (RecordControl) _player
.getControl("RecordControl");
_output = new ByteArrayOutputStream();
_rcontrol.setRecordStream(_output);
_rcontrol.startRecord();
_player.start();
catch (final Exception e)
UiApplication.getUiApplication().invokeAndWait(new Runnable()
public void run()
Dialog.inform(e.toString());
);
public void stop()
try
_rcontrol.commit();
_data = _output.toByteArray();
_output.close();
_player.close();
catch (Exception e)
synchronized (UiApplication.getEventLock())
Dialog.inform(e.toString());
byte[] getData()
return _data;
以及使用byte[]缓冲区绘制图形的方法:
private Bitmap getGraph(byte[] buffer, int zoom, int startFrom)
Bitmap result = new Bitmap(Display.getWidth(), Display.getHeight());
Graphics g = new Graphics(result);
g.setColor(Color.BLACK);
int xPos = 0;
int yPos = Display.getHeight() >> 1;
for (int i = startFrom; i < buffer.length; i += 2 * zoom)
byte[] b = new byte[] buffer[i], buffer[i + 1] ;
int level = (signedShortToInt(b) * 100 / 32767);
if (100 < level)
level -= 200;
g.drawPoint(xPos, yPos - level);
xPos++;
return result;
public static final int signedShortToInt(byte[] b)
int result = (b[0] & 0xff) | (b[1] & 0xff) << 8;
return result;
屏幕类:
class Scr extends MainScreen
BitmapField mGraphField = new BitmapField(new Bitmap(Display.getWidth(),
Display.getHeight()));
private VoiceNotesRecorderThread m_thread;
public Scr()
add(mGraphField);
add(new NullField(FOCUSABLE));
boolean mRecording = false;
private int mZoom = 1;
private int mStartFrom = 0;
byte[] mAudioData = null;
protected void makeMenu(Menu menu, int instance)
super.makeMenu(menu, instance);
menu.add(mRecordStopMenuItem);
menu.add(mPaintZoomIn);
menu.add(mPaintZoomOut);
menu.add(mPaintZoomToFitScreen);
menu.add(mPaintMoveRight);
menu.add(mPaintMoveLeft);
menu.add(mPaintMoveToBegin);
MenuItem mRecordStopMenuItem = new MenuItem("Record", 0, 0)
public void run()
if (!mRecording)
m_thread = new VoiceNotesRecorderThread();
m_thread.start();
mRecording = true;
this.setText("Stop");
else
m_thread.stop();
mAudioData = m_thread.getData();
zoomToFitScreen();
mRecording = false;
this.setText("Record");
;
MenuItem mPaintZoomIn = new MenuItem("Zoom In", 0, 0)
public void run()
zoomIn();
;
MenuItem mPaintZoomOut = new MenuItem("Zoom Out", 0, 0)
public void run()
zoomOut();
;
MenuItem mPaintZoomToFitScreen = new MenuItem("Fit Screen", 0, 0)
public void run()
zoomToFitScreen();
;
MenuItem mPaintMoveLeft = new MenuItem("Left", 0, 0)
public void run()
moveLeft();
;
MenuItem mPaintMoveRight = new MenuItem("Right", 0, 0)
public void run()
moveRight();
;
MenuItem mPaintMoveToBegin = new MenuItem("To Begin", 0, 0)
public void run()
moveToBegin();
;
private void zoomOut()
if (mZoom < 200)
mZoom++;
mGraphField.setBitmap(getGraph(mAudioData, mZoom, mStartFrom));
private void zoomIn()
if (mZoom > 1)
mZoom--;
mGraphField.setBitmap(getGraph(mAudioData, mZoom, mStartFrom));
private void zoomToFitScreen()
int lenght = mAudioData.length;
mZoom = (lenght / 2) / Display.getWidth();
mGraphField.setBitmap(getGraph(mAudioData, mZoom, mStartFrom));
private void moveRight()
if (mStartFrom < mAudioData.length - 30)
mStartFrom += 30;
mGraphField.setBitmap(getGraph(mAudioData, mZoom, mStartFrom));
private void moveLeft()
if (mStartFrom > 30)
mStartFrom -= 30;
mGraphField.setBitmap(getGraph(mAudioData, mZoom, mStartFrom));
private void moveToBegin()
mStartFrom = 0;
mGraphField.setBitmap(getGraph(mAudioData, mZoom, mStartFrom));
protected boolean navigationMovement(int dx, int dy, int status,
int time)
if (dx < 0)
moveLeft();
else if (dx > 0)
moveRight();
if (dy < 0)
zoomIn();
else if (dy > 0)
zoomOut();
return super.navigationMovement(dx, dy, status, time);
很有帮助:ADC -> integer PCM file -> signal processingSO - How is audio represented with numbers?Convert byte array to integer
【讨论】:
我不得不从您的帖子中删除图片,因为 ImageShack 已将其删除并替换为广告。请参阅meta.stackexchange.com/q/263771/215468 了解更多信息。如果可能,您最好重新上传它们。谢谢!【参考方案2】:在大多数设备中,仅支持具有单个轨道的 MID 格式。那是在一个轨道中支持多种乐器的 mid0 格式。我不确定 api 是否提供了测量信号幅度的工具。要将 mid 文件转换为您可以使用具有免费和专业版本的Anvil Studio
要录制音频,您需要使用 Manager.createPlayer("capture://audio")。还要将编码(PCM 或 AMR)留给设备实现,因为某些手机不支持 PCM/AMR
希望这会有所帮助!
【讨论】:
谢谢 Ram,我需要录制音频并从中测量信号电平,不能使用这种方法。但我会检查 midi,这也可能会有所帮助。以上是关于J2ME/Blackberry - 获取音频信号幅度级别?的主要内容,如果未能解决你的问题,请参考以下文章