国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Android 使用外置USB麥克風(fēng)MIC錄音遇到問題并解決(含錄音播放源碼)

這篇具有很好參考價(jià)值的文章主要介紹了Android 使用外置USB麥克風(fēng)MIC錄音遇到問題并解決(含錄音播放源碼)。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

一、遇到問題

  • 使用RK3399的開發(fā)板,跑Android8.1系統(tǒng)
  • 一開始插上外置的USB麥克風(fēng)的時(shí)候,無法使用

二、分析問題

  • 查看USB麥克風(fēng)拔插過程的debug打印日志

Android 使用外置USB麥克風(fēng)MIC錄音遇到問題并解決(含錄音播放源碼)

  • 插入U(xiǎn)SB麥克風(fēng)后,adb 查詢當(dāng)前聲卡信息
  • cat cards

Android 使用外置USB麥克風(fēng)MIC錄音遇到問題并解決(含錄音播放源碼)

三、解決問題

  • 通過分析發(fā)現(xiàn),USB麥克風(fēng)設(shè)備沒有枚舉出來,節(jié)點(diǎn)都沒掛載上去
  • 這時(shí)候就懷疑是硬件問題,USB麥克風(fēng)設(shè)備故障,或者USB供電不足,或者USB布線問題
  • 通過交叉實(shí)驗(yàn),拔插不同的USB口,更換RK3399開發(fā)板更換USB麥克風(fēng)
  • 最后確認(rèn)是USB麥克風(fēng)設(shè)備故障,更換USB麥克風(fēng)后,再cat cards就能查詢出USB-AUDIO設(shè)備

Android 使用外置USB麥克風(fēng)MIC錄音遇到問題并解決(含錄音播放源碼)

  • 使用USB麥克風(fēng)設(shè)備
    • 首先需要正常識(shí)別到該USB-AUDIO設(shè)備
    • 其次Android系統(tǒng)會(huì)自動(dòng)切換MIC錄音源
      • 如果沒有插入U(xiǎn)SB麥克風(fēng)設(shè)備,則Android系統(tǒng)使用主板上模擬MIC
      • 如果插入U(xiǎn)SB麥克風(fēng)設(shè)備,則Android系統(tǒng)就會(huì)切換到USB麥克風(fēng)

四、錄音源碼分析

  • audioSource: MediaRecorder.AudioSource.CAMCORDER, MediaRecorder.AudioSource.MIC 等
  • sampleRateInHz: 常用的有: 8000,11025,16000,22050,44100,96000;44100Hz是唯一可以保證兼容所有Android手機(jī)的采樣率
  • channelConfig: AudioFormat.CHANNEL_CONFIGURATION_DEFAULT,常用的是 CHANNEL_IN_MONO(單通道)CHANNEL_IN_STEREO(雙通道)
  • audioFormat: AudioFormat.ENCODING_PCM_16BIT, 測試中要捕獲PCM數(shù)據(jù)
  • bufferSizeInBytes: 由AudioRecord.getMinBufferSize(sampleRateInHz, channelConfig, audioFormat)獲得
public AudioRecord(int audioSource, int sampleRateInHz, int channelConfig, int audioFormat, int bufferSizeInBytes)
AudioRecord.startRecording();

AudioRecord.stop();

AudioRecord.read(byte[] audioData, int offsetInBytes, int sizeInBytes);
public class AudioCapturer {

    private static final String TAG = "AudioCapturer";
	
    private static final int DEFAULT_SOURCE = MediaRecorder.AudioSource.MIC;
    private static final int DEFAULT_SAMPLE_RATE = 44100;
    private static final int DEFAULT_CHANNEL_CONFIG = AudioFormat.CHANNEL_IN_STEREO;
    private static final int DEFAULT_AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT;

    private AudioRecord mAudioRecord;
    private int mMinBufferSize = 0;
	
    private Thread mCaptureThread; 	
    private boolean mIsCaptureStarted = false;
    private volatile boolean mIsLoopExit = false;

    private OnAudioFrameCapturedListener mAudioFrameCapturedListener;

    public interface OnAudioFrameCapturedListener {
        public void onAudioFrameCaptured(byte[] audioData);
    }	

    public boolean isCaptureStarted() {		
        return mIsCaptureStarted;
    }

    public void setOnAudioFrameCapturedListener(OnAudioFrameCapturedListener listener) {
        mAudioFrameCapturedListener = listener;
    }

    public boolean startCapture() {
        return startCapture(DEFAULT_SOURCE, DEFAULT_SAMPLE_RATE, DEFAULT_CHANNEL_CONFIG,
            DEFAULT_AUDIO_FORMAT);
    }

    public boolean startCapture(int audioSource, int sampleRateInHz, int channelConfig, int audioFormat) {

        if (mIsCaptureStarted) {
            Log.e(TAG, "Capture already started !");
            return false;
        }
    
        mMinBufferSize = AudioRecord.getMinBufferSize(sampleRateInHz,channelConfig,audioFormat);
        if (mMinBufferSize == AudioRecord.ERROR_BAD_VALUE) {
            Log.e(TAG, "Invalid parameter !");
            return false;
        }
        Log.d(TAG , "getMinBufferSize = "+mMinBufferSize+" bytes !");
		
        mAudioRecord = new AudioRecord(audioSource,sampleRateInHz,channelConfig,audioFormat,mMinBufferSize);				
        if (mAudioRecord.getState() == AudioRecord.STATE_UNINITIALIZED) {
    	    Log.e(TAG, "AudioRecord initialize fail !");
    	    return false;
        }		

        mAudioRecord.startRecording();

        mIsLoopExit = false;
        mCaptureThread = new Thread(new AudioCaptureRunnable());
        mCaptureThread.start();

        mIsCaptureStarted = true;

        Log.d(TAG, "Start audio capture success !");

        return true;
    }

    public void stopCapture() {

        if (!mIsCaptureStarted) {
            return;
        }

        mIsLoopExit = true;		
        try {
            mCaptureThread.interrupt();
            mCaptureThread.join(1000);
        } 
        catch (InterruptedException e) {		
            e.printStackTrace();
        }

        if (mAudioRecord.getRecordingState() == AudioRecord.RECORDSTATE_RECORDING) {
            mAudioRecord.stop();						
        }

        mAudioRecord.release();		
	
        mIsCaptureStarted = false;
        mAudioFrameCapturedListener = null;

        Log.d(TAG, "Stop audio capture success !");
    }

    private class AudioCaptureRunnable implements Runnable {		
	
        @Override
        public void run() {

            while (!mIsLoopExit) {

                byte[] buffer = new byte[mMinBufferSize];

                int ret = mAudioRecord.read(buffer, 0, mMinBufferSize);				
                if (ret == AudioRecord.ERROR_INVALID_OPERATION) {
                    Log.e(TAG , "Error ERROR_INVALID_OPERATION");
                } 
                else if (ret == AudioRecord.ERROR_BAD_VALUE) {
                    Log.e(TAG , "Error ERROR_BAD_VALUE");
                } 
                else { 
                    if (mAudioFrameCapturedListener != null) {
                        mAudioFrameCapturedListener.onAudioFrameCaptured(buffer);
                    }   
                    Log.d(TAG , "OK, Captured "+ret+" bytes !");
                }			
                
                SystemClock.sleep(10);
            }		
        }    
    }
}

五、播放源碼分析

  • streamType:
    • AudioManager.STREAM_VOCIE_CALL:電話聲音
    • AudioManager.STREAM_SYSTEM:系統(tǒng)聲音
    • AudioManager.STREAM_RING:鈴聲
    • AudioManager.STREAM_MUSCI:音樂聲
    • AudioManager.STREAM_ALARM:警告聲
    • AudioManager.STREAM_NOTIFICATION:通知聲
  • sampleRateInHz: 常用的有: 8000,11025,16000,22050,44100,96000;44100Hz是唯一可以保證兼容所有Android手機(jī)的采樣率
  • channelConfig: AudioFormat.CHANNEL_CONFIGURATION_DEFAULT,常用的是 CHANNEL_IN_MONO(單通道)
  • audioFormat: AudioFormat.ENCODING_PCM_16BIT, 測試中要捕獲PCM數(shù)據(jù)
  • bufferSizeInBytes: 由AudioRecord.getMinBufferSize(sampleRateInHz, channelConfig, audioFormat)獲得
  • mode:
    • AudioTrack.MODE_STATIC,一次性將所有的數(shù)據(jù)都寫入播放緩沖區(qū),簡單高效
    • AudioTrack.MODE_STREAM,按照一定的時(shí)間間隔不間斷地寫入音頻數(shù)據(jù)
public AudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat, int bufferSizeInBytes, int mode)
AudioTrack.play();
AudioTrack.stop();                        
import android.util.Log;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;

public class AudioPlayer {
    
    private static final String TAG = "AudioPlayer";

    private static final int DEFAULT_STREAM_TYPE = AudioManager.STREAM_MUSIC;
    private static final int DEFAULT_SAMPLE_RATE = 44100;
    private static final int DEFAULT_CHANNEL_CONFIG = AudioFormat.CHANNEL_IN_STEREO;
    private static final int DEFAULT_AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
    private static final int DEFAULT_PLAY_MODE = AudioTrack.MODE_STREAM;
            
    private boolean mIsPlayStarted = false;
    private int mMinBufferSize = 0;
    private AudioTrack mAudioTrack;  
    
    public boolean startPlayer() {
        return startPlayer(DEFAULT_STREAM_TYPE,DEFAULT_SAMPLE_RATE,DEFAULT_CHANNEL_CONFIG,DEFAULT_AUDIO_FORMAT);
    }
    
    public boolean startPlayer(int streamType, int sampleRateInHz, int channelConfig, int audioFormat) {
        
        if (mIsPlayStarted) {
            Log.e(TAG, "Player already started !");
            return false;
        }
        
        mMinBufferSize = AudioTrack.getMinBufferSize(sampleRateInHz,channelConfig,audioFormat);
        if (mMinBufferSize == AudioTrack.ERROR_BAD_VALUE) {
            Log.e(TAG, "Invalid parameter !");
            return false;
        }
        Log.d(TAG , "getMinBufferSize = "+mMinBufferSize+" bytes !");
        
        mAudioTrack = new AudioTrack(streamType,sampleRateInHz,channelConfig,audioFormat,mMinBufferSize,DEFAULT_PLAY_MODE);
        if (mAudioTrack.getState() == AudioTrack.STATE_UNINITIALIZED) {
            Log.e(TAG, "AudioTrack initialize fail !");
            return false;
        }            
        
        mIsPlayStarted = true;
        
        Log.d(TAG, "Start audio player success !");
        
        return true;
    }
    
    public int getMinBufferSize() {
        return mMinBufferSize;
    }
    
    public void stopPlayer() {
        
        if (!mIsPlayStarted) {
            return;
        }
        
        if (mAudioTrack.getPlayState() == AudioTrack.PLAYSTATE_PLAYING) {
            mAudioTrack.stop();                        
        }
        
        mAudioTrack.release();
        mIsPlayStarted = false;
           
        Log.d(TAG, "Stop audio player success !");
    }
    
    public boolean play(byte[] audioData, int offsetInBytes, int sizeInBytes) {
        
        if (!mIsPlayStarted) {
            Log.e(TAG, "Player not started !");
            return false;
        }
        
        if (sizeInBytes < mMinBufferSize) {
            Log.e(TAG, "audio data is not enough !");
            return false;
        }
        
        if (mAudioTrack.write(audioData,offsetInBytes,sizeInBytes) != sizeInBytes) {                
            Log.e(TAG, "Could not write all the samples to the audio device !");
        }                                   
                                                   
        mAudioTrack.play();
        
        Log.d(TAG , "OK, Played "+sizeInBytes+" bytes !");
        
        return true;
    }
}

六、參考

  • Jhuster/Android
  • android 采集PCM音頻數(shù)據(jù)并播放(支持USB攝像頭MIC)

覺得好,就一鍵三連唄(點(diǎn)贊+收藏+關(guān)注)文章來源地址http://www.zghlxwxcb.cn/news/detail-490521.html

到了這里,關(guān)于Android 使用外置USB麥克風(fēng)MIC錄音遇到問題并解決(含錄音播放源碼)的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Android麥克風(fēng)數(shù)據(jù)采集格式和常見的編碼格式

    在 Android 平臺(tái)上,PCM(脈沖編碼調(diào)制)數(shù)據(jù)是一種常用的音頻數(shù)據(jù)表示格式。PCM 是一種無損音頻編碼,可以捕捉和存儲(chǔ)原始音頻信號(hào)的波形。在 Android 系統(tǒng)中,開發(fā)人員可以使用 PCM 數(shù)據(jù)處理音頻信號(hào),以實(shí)現(xiàn)音頻播放、錄音、實(shí)時(shí)語音通信等功能。 在處理 PCM 數(shù)據(jù)時(shí),And

    2023年04月08日
    瀏覽(44)
  • 用Android手機(jī)充當(dāng)臺(tái)式電腦的攝像頭、麥克風(fēng)和音箱

    需要兩個(gè)軟件(都需要裝電腦端和手機(jī)端): DroidCam:起攝像頭和麥克風(fēng)的作用 AudioRelay:起輸出音頻的作用 步驟: 打開手機(jī)USB調(diào)試模式,連電腦(電腦沒反應(yīng)就重啟手機(jī)) 電腦、手機(jī)啟動(dòng)AudioRelay,在app界面下拉打開USB網(wǎng)絡(luò)共享,回到主界面隨便切換一下,看到DESKTOP字樣說

    2024年02月11日
    瀏覽(99)
  • Android WebView加載h5打開麥克風(fēng)與攝像頭的權(quán)限問題

    Android webview h5 麥克風(fēng)權(quán)限,攝像頭(相機(jī))權(quán)限實(shí)現(xiàn)與填坑。 app 必須先具備如下權(quán)限(本文只討論錄音與相機(jī)) AndroidManifest中添加: 注意:前面兩項(xiàng)需要app動(dòng)態(tài)申請 懶人快速做法(可直接copy代碼) 默許授權(quán)(不再確認(rèn)) 當(dāng)h5向app申請的時(shí)候,重寫 WebChromeClient 的onPermis

    2024年02月11日
    瀏覽(103)
  • Unity 使用 Microphone 采集麥克風(fēng)聲音

    1、獲取麥克風(fēng),Microphone.devices 2、開始錄音,Microphone.Start 3、結(jié)束錄音,Microphone.End 1、MicrophoneWrapper 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79

    2024年02月04日
    瀏覽(27)
  • Android 13 定制化開發(fā)--開啟相機(jī)或麥克風(fēng)時(shí),去掉狀態(tài)欄上的綠色圖標(biāo)

    Android 13 定制化開發(fā)--開啟相機(jī)或麥克風(fēng)時(shí),去掉狀態(tài)欄上的綠色圖標(biāo)

    ?Android?12 或更高版本的設(shè)備上,當(dāng)應(yīng)用使用麥克風(fēng)或相機(jī)時(shí),圖標(biāo)會(huì)出現(xiàn)在狀態(tài)欄中。如果應(yīng)用處于沉浸模式,圖標(biāo)會(huì)出現(xiàn)在屏幕的右上角。用戶可以打開“快捷設(shè)置”,并選擇圖標(biāo)以查看哪些應(yīng)用當(dāng)前正在使用麥克風(fēng)或攝像頭。圖 1?顯示了包含圖標(biāo)的示例屏幕截圖。 需求

    2024年04月24日
    瀏覽(25)
  • 使用手機(jī)作為電腦的麥克風(fēng)和攝像頭外設(shè)

    使用手機(jī)作為電腦的麥克風(fēng)和攝像頭外設(shè)

    Iriun 電腦端安裝:Iriun Android: Iriun 4K Webcam for PC and Mac - Apps on Google Play Apple: Iriun Webcam for PC and Mac on the App Store 基礎(chǔ)功能免費(fèi),普通使用足夠了。 付費(fèi)功能: 這里有介紹: 手機(jī)相機(jī)作為電腦攝像頭使用(Android、iPhone) - Bandicam(班迪錄屏) 手機(jī)和電腦在同一個(gè)局域網(wǎng)中就可以

    2024年02月01日
    瀏覽(88)
  • 音頻——數(shù)字麥克風(fēng)和模擬麥克風(fēng)(DMIC/AMIC)

    音頻——數(shù)字麥克風(fēng)和模擬麥克風(fēng)(DMIC/AMIC)

    麥克風(fēng) (microphone):是將聲音信號(hào)轉(zhuǎn)換為電信號(hào)的能量轉(zhuǎn)換器件,也就是用來采集你說話的聲音 揚(yáng)聲器 (speaker):是一種把電信號(hào)轉(zhuǎn)變?yōu)槁曅盘?hào)的換能器件,就是把對方說話產(chǎn)生的電信號(hào)轉(zhuǎn)換成聲音播放出來。 簡單來說,麥克風(fēng)的功能是采集聲音,揚(yáng)聲器的功能是播放聲音。

    2024年02月10日
    瀏覽(22)
  • 使用STM32的I2S協(xié)議讀取麥克風(fēng)INMP441

    使用STM32的I2S協(xié)議讀取麥克風(fēng)INMP441

    本文將詳細(xì)介紹使用STM32的硬件I2S協(xié)議,從麥克風(fēng)模塊INMP441讀取音頻信號(hào)的步驟和避坑指南。 點(diǎn)這里,從Github下載工程文件 百度網(wǎng)盤: 鏈接:https://pan.baidu.com/s/1cglAGirn6bTQhIEpWDb7Ig?pwd=k9gh 提取碼:k9gh INMP441模塊: 主控芯片:我用的是STM32F103ZET6,可以在STM的選型手冊上看到哪

    2024年02月02日
    瀏覽(18)
  • 傳感器使用——ESP-WROOM-32 and INMP441麥克風(fēng)音頻采集

    傳感器使用——ESP-WROOM-32 and INMP441麥克風(fēng)音頻采集

    ?????????使用不同傳感器前需要了解其連接及通信方式。對于 ESP-WROOM-32 and INMP441麥克風(fēng) 是通過 I2S 方式進(jìn)行通信。具體連接引腳參照下圖: ESP-WROOM-32引腳示意圖 ? ? ? ? ?使用的麥克風(fēng)為MEMS麥克風(fēng),具體規(guī)格可參照芯片規(guī)格數(shù)說明。 INMP441麥克風(fēng) ????????I2S音頻連接

    2024年02月09日
    瀏覽(20)
  • MacOS 為指定應(yīng)用添加指定權(quán)限(瀏覽器無法使用攝像頭、麥克風(fēng)終極解決方案)

    MacOS 為指定應(yīng)用添加指定權(quán)限(瀏覽器無法使用攝像頭、麥克風(fēng)終極解決方案)

    起因:需要瀏覽器在線做一些測評,但我的 Chrome 沒有攝像頭/麥克風(fēng)權(quán)限,并且在設(shè)置中是沒有手動(dòng)添加按鈕的。 我嘗試了重裝軟件,更新系統(tǒng)(上面的 13.5 就是這么來的,我本來都半年懶得更新系統(tǒng)了),都沒有任何用。 系統(tǒng)版本:MacOS 13.5.1(需要開啟 sip,可參考 macOS

    2024年02月07日
    瀏覽(22)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包