public boolean testRecord() throws Exception { AudioStream stream = getRecordedStream(); if (stream != null) { audioSpec.inferResultsFrom(stream); // do not move this before the corrector return stream.isValid(recordTimeMS) && stream.isDecodeable(); } else return false; }
@Override public synchronized void start() throws IllegalStateException, IOException { if (!mStreaming) { configure(); super.start(); } }
/** Stops the stream. */ public synchronized void stop() { if (mStreaming) { Log.d(TAG, "Interrupting threads..."); mThread.interrupt(); mAudioRecord.stop(); mAudioRecord.release(); mAudioRecord = null; super.stop(); } }
public synchronized void configure() throws IllegalStateException, IOException { super.configure(); mQuality = mRequestedQuality.clone(); // Checks if the user has supplied an exotic sampling rate int i = 0; for (; i < AUDIO_SAMPLING_RATES.length; i++) { if (AUDIO_SAMPLING_RATES[i] == mQuality.samplingRate) { mSamplingRateIndex = i; break; } } // If he did, we force a reasonable one: 16 kHz if (i > 12) mQuality.samplingRate = 16000; if (mMode != mRequestedMode || mPacketizer == null) { mMode = mRequestedMode; mPacketizer = new AACLATMPacketizer(); mPacketizer.setDestination(mDestination, mRtpPort, mRtcpPort); mPacketizer.getRtpSocket().setOutputStream(mOutputStream, mChannelIdentifier); } mProfile = 2; // AAC LC mChannel = 1; mConfig = mProfile << 11 | mSamplingRateIndex << 7 | mChannel << 3; mSessionDescription = "m=audio " + String.valueOf(getDestinationPorts()[0]) + " RTP/AVP 96\r\n" + "a=rtpmap:96 mpeg4-generic/" + mQuality.samplingRate + "\r\n" + "a=fmtp:96 streamtype=5; profile-level-id=15; mode=AAC-hbr; config=" + Integer.toHexString(mConfig) + "; SizeLength=13; IndexLength=3; IndexDeltaLength=3;\r\n"; }
/** * Records a short sample of AAC ADTS from the microphone to find out what the sampling rate * really is On some phone indeed, no error will be reported if the sampling rate used differs * from the one selected with setAudioSamplingRate * * @throws IOException * @throws IllegalStateException */ private void testADTS() throws IllegalStateException, IOException { if (mSettings != null) { if (mSettings.contains("aac-" + mSamplingRate)) { String[] s = mSettings.getString("aac-" + mSamplingRate, "").split(","); mActualSamplingRate = Integer.valueOf(s[0]); mConfig = Integer.valueOf(s[1]); mChannel = Integer.valueOf(s[2]); return; } } final String TESTFILE = Environment.getExternalStorageDirectory().getPath() + "/spydroid-test.adts"; if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { throw new IllegalStateException("No external storage or external storage not ready !"); } // The structure of an ADTS packet is described here: // http://wiki.multimedia.cx/index.php?title=ADTS // ADTS header is 7 or 9 bytes long byte[] buffer = new byte[9]; // That means the H264Stream will behave as a regular MediaRecorder object // it will not start the packetizer thread and can be used to save video in a file setMode(MODE_DEFAULT); mMediaRecorder.setOutputFile(TESTFILE); super.prepare(); start(); // We record for 1 sec // TODO: use the MediaRecorder.OnInfoListener try { Thread.sleep(1000); } catch (InterruptedException e) { } stop(); setMode(MODE_STREAMING); File file = new File(TESTFILE); RandomAccessFile raf = new RandomAccessFile(file, "r"); // ADTS packets start with a sync word: 12bits set to 1 while (true) { if ((raf.readByte() & 0xFF) == 0xFF) { buffer[0] = raf.readByte(); if ((buffer[0] & 0xF0) == 0xF0) break; } } raf.read(buffer, 1, 5); mSamplingRateIndex = (buffer[1] & 0x3C) >> 2; mProfile = ((buffer[1] & 0xC0) >> 6) + 1; mChannel = (buffer[1] & 0x01) << 2 | (buffer[2] & 0xC0) >> 6; mActualSamplingRate = sADTSSamplingRates[mSamplingRateIndex]; // 5 bits for the object type / 4 bits for the sampling rate / 4 bits for the channel / padding mConfig = mProfile << 11 | mSamplingRateIndex << 7 | mChannel << 3; Log.i(TAG, "MPEG VERSION: " + ((buffer[0] & 0x08) >> 3)); Log.i(TAG, "PROTECTION: " + (buffer[0] & 0x01)); Log.i(TAG, "PROFILE: " + sAudioObjectTypes[mProfile]); Log.i(TAG, "SAMPLING FREQUENCY: " + mActualSamplingRate); Log.i(TAG, "CHANNEL: " + mChannel); raf.close(); if (mSettings != null) { Editor editor = mSettings.edit(); editor.putString( "aac-" + mSamplingRate, mActualSamplingRate + "," + mConfig + "," + mChannel); editor.commit(); } if (!file.delete()) Log.e(TAG, "Temp file could not be erased"); }
public void prepare() throws IllegalStateException, IOException { testADTS(); ((AACADTSPacketizer) mPacketizer).setSamplingRate(mActualSamplingRate); super.prepare(); }