AudioRecord.java revision 076357b8567458d4b6dfdcf839ef751634cd2bfb
1/* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.media; 18 19import java.lang.ref.WeakReference; 20import java.io.OutputStream; 21import java.io.IOException; 22import java.lang.IllegalArgumentException; 23import java.lang.IllegalStateException; 24import java.lang.Thread; 25import java.nio.ByteBuffer; 26 27import android.os.Handler; 28import android.os.Looper; 29import android.os.Message; 30import android.util.Log; 31 32/** 33 * The AudioRecord class manages the audio resources for Java applications 34 * to record audio from the audio input hardware of the platform. This is 35 * achieved by "pulling" (reading) the data from the AudioRecord object. The 36 * application is responsible for polling the AudioRecord object in time using one of 37 * the following three methods: {@link #read(byte[],int, int)}, {@link #read(short[], int, int)} 38 * or {@link #read(ByteBuffer, int)}. The choice of which method to use will be based 39 * on the audio data storage format that is the most convenient for the user of AudioRecord. 40 * <p>Upon creation, an AudioRecord object initializes its associated audio buffer that it will 41 * fill with the new audio data. The size of this buffer, specified during the construction, 42 * determines how long an AudioRecord can record before "over-running" data that has not 43 * been read yet. Data should be from the audio hardware in chunks of sizes inferior to 44 * the total recording buffer size. 45 */ 46public class AudioRecord 47{ 48 //--------------------------------------------------------- 49 // Constants 50 //-------------------- 51 /** 52 * State of an AudioRecord that was not successfully initialized upon creation 53 */ 54 public static final int STATE_UNINITIALIZED = 0; 55 /** 56 * State of an AudioRecord that is ready to be used 57 */ 58 public static final int STATE_INITIALIZED = 1; 59 60 /** 61 * State of an AudioRecord this is not recording 62 */ 63 public static final int RECORDSTATE_STOPPED = 1; // matches SL_RECORDSTATE_STOPPED 64 /** 65 * State of an AudioRecord this is recording 66 */ 67 public static final int RECORDSTATE_RECORDING = 3;// matches SL_RECORDSTATE_RECORDING 68 69 // Error codes: 70 // to keep in sync with frameworks/base/core/jni/android_media_AudioRecord.cpp 71 /** 72 * Denotes a successful operation. 73 */ 74 public static final int SUCCESS = 0; 75 /** 76 * Denotes a generic operation failure. 77 */ 78 public static final int ERROR = -1; 79 /** 80 * Denotes a failure due to the use of an invalid value. 81 */ 82 public static final int ERROR_BAD_VALUE = -2; 83 /** 84 * Denotes a failure due to the improper use of a method. 85 */ 86 public static final int ERROR_INVALID_OPERATION = -3; 87 88 private static final int AUDIORECORD_ERROR_SETUP_ZEROFRAMECOUNT = -16; 89 private static final int AUDIORECORD_ERROR_SETUP_INVALIDCHANNELCOUNT = -17; 90 private static final int AUDIORECORD_ERROR_SETUP_INVALIDFORMAT = -18; 91 private static final int AUDIORECORD_ERROR_SETUP_INVALIDSTREAMTYPE = -19; 92 private static final int AUDIORECORD_ERROR_SETUP_NATIVEINITFAILED = -20; 93 94 // Events: 95 // to keep in sync with frameworks/base/include/media/AudioRecord.h 96 /** 97 * Event id for when the recording head has reached a previously set marker. 98 */ 99 private static final int NATIVE_EVENT_MARKER = 2; 100 /** 101 * Event id for when the previously set update period has passed during recording. 102 */ 103 private static final int NATIVE_EVENT_NEW_POS = 3; 104 105 private final static String TAG = "AudioRecord-Java"; 106 107 108 //--------------------------------------------------------- 109 // Used exclusively by native code 110 //-------------------- 111 /** 112 * Accessed by native methods: provides access to C++ AudioRecord object 113 */ 114 @SuppressWarnings("unused") 115 private int mNativeRecorderInJavaObj; 116 /** 117 * Accessed by native methods: provides access to record source constants 118 */ 119 @SuppressWarnings("unused") 120 private final static int SOURCE_DEFAULT = MediaRecorder.AudioSource.DEFAULT; 121 @SuppressWarnings("unused") 122 private final static int SOURCE_MIC = MediaRecorder.AudioSource.MIC; 123 /** 124 * Accessed by native methods: provides access to the callback data. 125 */ 126 @SuppressWarnings("unused") 127 private int mNativeCallbackCookie; 128 129 130 //--------------------------------------------------------- 131 // Member variables 132 //-------------------- 133 /** 134 * The audio data sampling rate in Hz. 135 */ 136 private int mSampleRate = 22050; 137 /** 138 * The number of input audio channels (1 is mono, 2 is stereo) 139 */ 140 private int mChannelCount = 1; 141 /** 142 * The current audio channel configuration 143 */ 144 private int mChannelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO; 145 /** 146 * The encoding of the audio samples. 147 * @see AudioFormat#ENCODING_PCM_8BIT 148 * @see AudioFormat#ENCODING_PCM_16BIT 149 */ 150 private int mAudioFormat = AudioFormat.ENCODING_PCM_16BIT; 151 /** 152 * Where the audio data is recorded from. 153 */ 154 private int mRecordSource = MediaRecorder.AudioSource.DEFAULT; 155 /** 156 * Indicates the state of the AudioRecord instance. 157 */ 158 private int mState = STATE_UNINITIALIZED; 159 /** 160 * Indicates the recording state of the AudioRecord instance. 161 */ 162 private int mRecordingState = RECORDSTATE_STOPPED; 163 /** 164 * Lock to make sure mRecordingState updates are reflecting the actual state of the object. 165 */ 166 private Object mRecordingStateLock = new Object(); 167 /** 168 * The listener the AudioRecord notifies when a previously set marker is reached. 169 * @see #setMarkerReachedListener(OnMarkerReachedListener) 170 */ 171 private OnMarkerReachedListener mMarkerListener = null; 172 /** 173 * Lock to protect marker listener updates against event notifications 174 */ 175 private final Object mMarkerListenerLock = new Object(); 176 /** 177 * The listener the AudioRecord notifies periodically during recording. 178 * @see #setPeriodicNotificationListener(OnPeriodicNotificationListener) 179 */ 180 private OnPeriodicNotificationListener mPeriodicListener = null; 181 /** 182 * Lock to protect periodic listener updates against event notifications 183 */ 184 private final Object mPeriodicListenerLock = new Object(); 185 /** 186 * Handler for events coming from the native code 187 */ 188 private NativeEventHandler mNativeEventHandler = null; 189 /** 190 * Size of the native audio buffer. 191 */ 192 private int mNativeBufferSizeInBytes = 0; 193 194 195 //--------------------------------------------------------- 196 // Constructor, Finalize 197 //-------------------- 198 /** 199 * Class constructor. 200 * @param audioSource the recording source. See {@link MediaRecorder.AudioSource} for 201 * recording source definitions. 202 * @param sampleRateInHz the sample rate expressed in Hertz. Examples of rates are (but 203 * not limited to) 44100, 22050 and 11025. 204 * @param channelConfig describes the configuration of the audio channels. 205 * See {@link AudioFormat#CHANNEL_CONFIGURATION_MONO} and 206 * {@link AudioFormat#CHANNEL_CONFIGURATION_STEREO} 207 * @param audioFormat the format in which the audio data is represented. 208 * See {@link AudioFormat#ENCODING_PCM_16BIT} and 209 * {@link AudioFormat#ENCODING_PCM_8BIT} 210 * @param bufferSizeInBytes the total size (in bytes) of the buffer where audio data is written 211 * to during the recording. New audio data can be read from this buffer in smaller chunks 212 * than this size. 213 * @throws java.lang.IllegalArgumentException 214 */ 215 public AudioRecord(int audioSource, int sampleRateInHz, int channelConfig, int audioFormat, 216 int bufferSizeInBytes) 217 throws IllegalArgumentException { 218 mState = STATE_UNINITIALIZED; 219 mRecordingState = RECORDSTATE_STOPPED; 220 221 audioParamCheck(audioSource, sampleRateInHz, channelConfig, audioFormat); 222 223 audioBuffSizeCheck(bufferSizeInBytes); 224 225 // native initialization 226 //TODO: update native initialization when information about hardware init failure 227 // due to capture device already open is available. 228 int initResult = native_setup( new WeakReference<AudioRecord>(this), 229 mRecordSource, mSampleRate, mChannelCount, mAudioFormat, mNativeBufferSizeInBytes); 230 if (initResult != SUCCESS) { 231 loge("Error code "+initResult+" when initializing native AudioRecord object."); 232 return; // with mState == STATE_UNINITIALIZED 233 } 234 235 mState = STATE_INITIALIZED; 236 } 237 238 239 // Convenience method for the constructor's parameter checks. 240 // This is where constructor IllegalArgumentException-s are thrown 241 // postconditions: 242 // mRecordSource is valid 243 // mChannelCount is valid 244 // mAudioFormat is valid 245 // mSampleRate is valid 246 private void audioParamCheck(int audioSource, int sampleRateInHz, 247 int channelConfig, int audioFormat) { 248 249 //-------------- 250 // audio source 251 if ( (audioSource != MediaRecorder.AudioSource.DEFAULT) 252 && (audioSource != MediaRecorder.AudioSource.MIC) ) { 253 throw (new IllegalArgumentException("Invalid audio source.")); 254 } else { 255 mRecordSource = audioSource; 256 } 257 258 //-------------- 259 // sample rate 260 if ( (sampleRateInHz < 4000) || (sampleRateInHz > 48000) ) { 261 throw (new IllegalArgumentException(sampleRateInHz 262 + "Hz is not a supported sample rate.")); 263 } else { 264 mSampleRate = sampleRateInHz; 265 } 266 267 //-------------- 268 // channel config 269 switch (channelConfig) { 270 case AudioFormat.CHANNEL_CONFIGURATION_DEFAULT: 271 case AudioFormat.CHANNEL_CONFIGURATION_MONO: 272 mChannelCount = 1; 273 mChannelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO; 274 break; 275 case AudioFormat.CHANNEL_CONFIGURATION_STEREO: 276 mChannelCount = 2; 277 mChannelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_STEREO; 278 break; 279 default: 280 mChannelCount = 0; 281 mChannelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_INVALID; 282 throw (new IllegalArgumentException("Unsupported channel configuration.")); 283 } 284 285 //-------------- 286 // audio format 287 switch (audioFormat) { 288 case AudioFormat.ENCODING_DEFAULT: 289 mAudioFormat = AudioFormat.ENCODING_PCM_16BIT; 290 break; 291 case AudioFormat.ENCODING_PCM_16BIT: 292 case AudioFormat.ENCODING_PCM_8BIT: 293 mAudioFormat = audioFormat; 294 break; 295 default: 296 mAudioFormat = AudioFormat.ENCODING_INVALID; 297 throw (new IllegalArgumentException("Unsupported sample encoding." 298 + " Should be ENCODING_PCM_8BIT or ENCODING_PCM_16BIT.")); 299 } 300 } 301 302 303 // Convenience method for the contructor's audio buffer size check. 304 // preconditions: 305 // mChannelCount is valid 306 // mAudioFormat is AudioFormat.ENCODING_PCM_8BIT OR AudioFormat.ENCODING_PCM_16BIT 307 // postcondition: 308 // mNativeBufferSizeInBytes is valid (multiple of frame size, positive) 309 private void audioBuffSizeCheck(int audioBufferSize) { 310 // NB: this section is only valid with PCM data. 311 // To update when supporting compressed formats 312 int frameSizeInBytes = mChannelCount 313 * (mAudioFormat == AudioFormat.ENCODING_PCM_8BIT ? 1 : 2); 314 if ((audioBufferSize % frameSizeInBytes != 0) || (audioBufferSize < 1)) { 315 throw (new IllegalArgumentException("Invalid audio buffer size.")); 316 } 317 318 mNativeBufferSizeInBytes = audioBufferSize; 319 } 320 321 322 // Convenience method for the creation of the native event handler 323 // It is called only when a non-null event listener is set. 324 // precondition: 325 // mNativeEventHandler is null 326 private void createNativeEventHandler() { 327 Looper looper; 328 if ((looper = Looper.myLooper()) != null) { 329 mNativeEventHandler = new NativeEventHandler(this, looper); 330 } else if ((looper = Looper.getMainLooper()) != null) { 331 mNativeEventHandler = new NativeEventHandler(this, looper); 332 } else { 333 mNativeEventHandler = null; 334 } 335 } 336 337 338 /** 339 * Releases the native AudioRecord resources. 340 */ 341 public void release() { 342 try { 343 stop(); 344 } catch(IllegalStateException ise) { 345 // don't raise an exception, we're releasing the resources. 346 } 347 native_release(); 348 mState = STATE_UNINITIALIZED; 349 } 350 351 352 @Override 353 protected void finalize() { 354 native_finalize(); 355 } 356 357 358 //-------------------------------------------------------------------------- 359 // Getters 360 //-------------------- 361 /** 362 * Returns the configured audio data sample rate in Hz 363 */ 364 public int getSampleRate() { 365 return mSampleRate; 366 } 367 368 /** 369 * Returns the audio recording source. 370 * @see MediaRecorder.AudioSource 371 */ 372 public int getAudioSource() { 373 return mRecordSource; 374 } 375 376 /** 377 * Returns the configured audio data format. See {@link AudioFormat#ENCODING_PCM_16BIT} 378 * and {@link AudioFormat#ENCODING_PCM_8BIT}. 379 */ 380 public int getAudioFormat() { 381 return mAudioFormat; 382 } 383 384 /** 385 * Returns the configured channel configuration. 386 * See {@link AudioFormat#CHANNEL_CONFIGURATION_MONO} 387 * and {@link AudioFormat#CHANNEL_CONFIGURATION_STEREO}. 388 */ 389 public int getChannelConfiguration() { 390 return mChannelConfiguration; 391 } 392 393 /** 394 * Returns the configured number of channels. 395 */ 396 public int getChannelCount() { 397 return mChannelCount; 398 } 399 400 /** 401 * Returns the state of the AudioRecord instance. This is useful after the 402 * AudioRecord instance has been created to check if it was initialized 403 * properly. This ensures that the appropriate hardware resources have been 404 * acquired. 405 * @see AudioRecord#STATE_INITIALIZED 406 * @see AudioRecord#STATE_UNINITIALIZED 407 */ 408 public int getState() { 409 return mState; 410 } 411 412 /** 413 * Returns the recording state of the AudioRecord instance. 414 * @see AudioRecord#RECORDSTATE_STOPPED 415 * @see AudioRecord#RECORDSTATE_RECORDING 416 */ 417 public int getRecordingState() { 418 return mRecordingState; 419 } 420 421 /** 422 * @return marker position in frames 423 */ 424 public int getNotificationMarkerPosition() { 425 return native_get_marker_pos(); 426 } 427 428 /** 429 * @return update period in frames 430 */ 431 public int getPositionNotificationPeriod() { 432 return native_get_pos_update_period(); 433 } 434 435 /** 436 * {@hide} 437 * Returns the minimum buffer size required for the successful creation of an AudioRecord 438 * object. 439 * @param sampleRateInHz the sample rate expressed in Hertz. 440 * @param channelConfig describes the configuration of the audio channels. 441 * See {@link AudioFormat#CHANNEL_CONFIGURATION_MONO} and 442 * {@link AudioFormat#CHANNEL_CONFIGURATION_STEREO} 443 * @param audioFormat the format in which the audio data is represented. 444 * See {@link AudioFormat#ENCODING_PCM_16BIT}. 445 * @return {@link #ERROR_BAD_VALUE} if the recording parameters are not supported by the 446 * hardware, or an invalid parameter was passed, 447 * or {@link #ERROR} if the implementation was unable to query the hardware for its 448 * output properties, 449 * or the minimum buffer size expressed in of bytes. 450 */ 451 static public int getMinBufferSize(int sampleRateInHz, int channelConfig, int audioFormat) { 452 int channelCount = 0; 453 switch(channelConfig) { 454 case AudioFormat.CHANNEL_CONFIGURATION_DEFAULT: 455 case AudioFormat.CHANNEL_CONFIGURATION_MONO: 456 channelCount = 1; 457 break; 458 case AudioFormat.CHANNEL_CONFIGURATION_STEREO: 459 channelCount = 2; 460 break; 461 case AudioFormat.CHANNEL_CONFIGURATION_INVALID: 462 default: 463 loge("getMinBufferSize(): Invalid channel configuration."); 464 return AudioRecord.ERROR_BAD_VALUE; 465 } 466 467 // PCM_8BIT is not supported at the moment 468 if (audioFormat != AudioFormat.ENCODING_PCM_16BIT) { 469 loge("getMinBufferSize(): Invalid audio format."); 470 return AudioRecord.ERROR_BAD_VALUE; 471 } 472 473 int size = native_get_min_buff_size(sampleRateInHz, channelCount, audioFormat); 474 if (size == 0) { 475 return AudioRecord.ERROR_BAD_VALUE; 476 } 477 else if (size == -1) { 478 return AudioRecord.ERROR; 479 } 480 else { 481 return size; 482 } 483 } 484 485 486 //--------------------------------------------------------- 487 // Transport control methods 488 //-------------------- 489 /** 490 * Starts recording from the AudioRecord instance. 491 * @throws IllegalStateException 492 */ 493 public void startRecording() 494 throws IllegalStateException { 495 if (mState != STATE_INITIALIZED) { 496 throw(new IllegalStateException("startRecording() called on an " 497 +"uninitialized AudioRecord.")); 498 } 499 500 // start recording 501 synchronized(mRecordingStateLock) { 502 native_start(); 503 mRecordingState = RECORDSTATE_RECORDING; 504 } 505 } 506 507 508 509 /** 510 * Stops recording. 511 * @throws IllegalStateException 512 */ 513 public void stop() 514 throws IllegalStateException { 515 if (mState != STATE_INITIALIZED) { 516 throw(new IllegalStateException("stop() called on an uninitialized AudioRecord.")); 517 } 518 519 // stop recording 520 synchronized(mRecordingStateLock) { 521 native_stop(); 522 mRecordingState = RECORDSTATE_STOPPED; 523 } 524 } 525 526 527 //--------------------------------------------------------- 528 // Audio data supply 529 //-------------------- 530 /** 531 * Reads audio data from the audio hardware for recording into a buffer. 532 * @param audioData the array to which the recorded audio data is written. 533 * @param offsetInBytes index in audioData from which the data is written. 534 * @param sizeInBytes the number of requested bytes. 535 * @return the number of bytes that were read or -1 if the object wasn't properly 536 * initialized. The number of bytes will not exceed sizeInBytes. 537 */ 538 public int read(byte[] audioData, int offsetInBytes, int sizeInBytes) { 539 if (mState != STATE_INITIALIZED) { 540 return -1; 541 } 542 543 return native_read_in_byte_array(audioData, offsetInBytes, sizeInBytes); 544 } 545 546 547 /** 548 * Reads audio data from the audio hardware for recording into a buffer. 549 * @param audioData the array to which the recorded audio data is written. 550 * @param offsetInShorts index in audioData from which the data is written. 551 * @param sizeInShorts the number of requested shorts. 552 * @return the number of shorts that were read. or -1 if the object wasn't properly 553 * initialized. The number of shorts will not exceed sizeInShorts 554 */ 555 public int read(short[] audioData, int offsetInShorts, int sizeInShorts) { 556 if (mState != STATE_INITIALIZED) { 557 return -1; 558 } 559 560 return native_read_in_short_array(audioData, offsetInShorts, sizeInShorts); 561 } 562 563 564 /** 565 * Reads audio data from the audio hardware for recording into a direct buffer. If this buffer 566 * is not a direct buffer, this method will always return 0. 567 * @param audioBuffer the direct buffer to which the recorded audio data is written. 568 * @param sizeInBytes the number of requested bytes. 569 * @return the number of bytes that were read or -1 if the object wasn't properly 570 * initialized. The number of bytes will not exceed sizeInBytes. 571 */ 572 public int read(ByteBuffer audioBuffer, int sizeInBytes) { 573 if (mState != STATE_INITIALIZED) { 574 return -1; 575 } 576 577 return native_read_in_direct_buffer(audioBuffer, sizeInBytes); 578 } 579 580 581 //-------------------------------------------------------------------------- 582 // Initialization / configuration 583 //-------------------- 584 /** 585 * Sets the listener the AudioRecord notifies when a previously set marker is reached. 586 * @param listener 587 */ 588 public void setMarkerReachedListener(OnMarkerReachedListener listener) { 589 synchronized (mMarkerListenerLock) { 590 mMarkerListener = listener; 591 } 592 if ((listener != null) && (mNativeEventHandler == null)) { 593 createNativeEventHandler(); 594 } 595 } 596 597 598 /** 599 * Sets the listener the AudioRecord notifies periodically during recording. 600 * @param listener 601 */ 602 public void setPeriodicNotificationListener(OnPeriodicNotificationListener listener) { 603 synchronized (mPeriodicListenerLock) { 604 mPeriodicListener = listener; 605 } 606 if ((listener != null) && (mNativeEventHandler == null)) { 607 createNativeEventHandler(); 608 } 609 } 610 611 612 /** 613 * Sets the marker position at which the listener, if set with 614 * {@link #setMarkerReachedListener(OnMarkerReachedListener)}, is called. 615 * @param markerInFrames marker position expressed in frames 616 * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_BAD_VALUE}, 617 * {@link #ERROR_INVALID_OPERATION} 618 */ 619 public int setNotificationMarkerPosition(int markerInFrames) { 620 return native_set_marker_pos(markerInFrames); 621 } 622 623 624 /** 625 * Sets the period at which the listener, if set with 626 * {@link #setPositionNotificationPeriod(int)}, is called. 627 * @param periodInFrames update period expressed in frames 628 * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_INVALID_OPERATION} 629 */ 630 public int setPositionNotificationPeriod(int periodInFrames) { 631 return native_set_pos_update_period(periodInFrames); 632 } 633 634 635 //--------------------------------------------------------- 636 // Interface definitions 637 //-------------------- 638 /** 639 * Interface definition for a callback to be invoked when an AudioRecord has 640 * reached a notification marker set by setNotificationMarkerPosition(). 641 */ 642 public interface OnMarkerReachedListener { 643 /** 644 * Called on the listener to notify it that the previously set marker has been reached 645 * by the recording head. 646 */ 647 void onMarkerReached(AudioRecord recorder); 648 } 649 650 651 /** 652 * Interface definition for a callback to be invoked for each periodic AudioRecord 653 * update during recording. The update interval is set by setPositionNotificationPeriod(). 654 */ 655 public interface OnPeriodicNotificationListener { 656 /** 657 * Called on the listener to periodically notify it that the recording head has reached 658 * a multiple of the notification period. 659 */ 660 void onPeriodicNotification(AudioRecord recorder); 661 } 662 663 664 //--------------------------------------------------------- 665 // Inner classes 666 //-------------------- 667 /** 668 * Helper class to handle the forwarding of native events to the appropriate listeners 669 */ 670 private class NativeEventHandler extends Handler 671 { 672 private AudioRecord mAudioRecord; 673 674 public NativeEventHandler(AudioRecord ar, Looper looper) { 675 super(looper); 676 mAudioRecord = ar; 677 } 678 679 @Override 680 public void handleMessage(Message msg) { 681 if (mAudioRecord == null) { 682 return; 683 } 684 switch(msg.what) { 685 case NATIVE_EVENT_MARKER: 686 synchronized (mMarkerListenerLock) { 687 if (mAudioRecord.mMarkerListener != null) { 688 mAudioRecord.mMarkerListener.onMarkerReached(mAudioRecord); 689 } 690 } 691 break; 692 case NATIVE_EVENT_NEW_POS: 693 synchronized (mPeriodicListenerLock) { 694 if (mAudioRecord.mPeriodicListener != null) { 695 mAudioRecord.mPeriodicListener.onPeriodicNotification(mAudioRecord); 696 } 697 } 698 break; 699 default: 700 Log.e(TAG, "[ android.media.AudioRecord.NativeEventHandler ] " + 701 "Unknown event type: " + msg.what); 702 break; 703 } 704 } 705 } 706 707 708 //--------------------------------------------------------- 709 // Java methods called from the native side 710 //-------------------- 711 @SuppressWarnings("unused") 712 private static void postEventFromNative(Object audiorecord_ref, 713 int what, int arg1, int arg2, Object obj) { 714 //logd("Event posted from the native side: event="+ what + " args="+ arg1+" "+arg2); 715 AudioRecord recorder = (AudioRecord)((WeakReference)audiorecord_ref).get(); 716 if (recorder == null) { 717 return; 718 } 719 720 if (recorder.mNativeEventHandler != null) { 721 Message m = recorder.mNativeEventHandler.obtainMessage(what, arg1, arg2, obj); 722 recorder.mNativeEventHandler.sendMessage(m); 723 } 724 725 } 726 727 728 //--------------------------------------------------------- 729 // Native methods called from the Java side 730 //-------------------- 731 732 private native final int native_setup(Object audiorecord_this, 733 int recordSource, int sampleRate, int nbChannels, int audioFormat, int buffSizeInBytes); 734 735 private native final void native_finalize(); 736 737 private native final void native_release(); 738 739 private native final void native_start(); 740 741 private native final void native_stop(); 742 743 private native final int native_read_in_byte_array(byte[] audioData, 744 int offsetInBytes, int sizeInBytes); 745 746 private native final int native_read_in_short_array(short[] audioData, 747 int offsetInShorts, int sizeInShorts); 748 749 private native final int native_read_in_direct_buffer(Object jBuffer, int sizeInBytes); 750 751 private native final int native_set_marker_pos(int marker); 752 private native final int native_get_marker_pos(); 753 754 private native final int native_set_pos_update_period(int updatePeriod); 755 private native final int native_get_pos_update_period(); 756 757 static private native final int native_get_min_buff_size( 758 int sampleRateInHz, int channelCount, int audioFormat); 759 760 761 //--------------------------------------------------------- 762 // Utility methods 763 //------------------ 764 765 private static void logd(String msg) { 766 Log.d(TAG, "[ android.media.AudioRecord ] " + msg); 767 } 768 769 private static void loge(String msg) { 770 Log.e(TAG, "[ android.media.AudioRecord ] " + msg); 771 } 772 773} 774 775 776 777 778 779