Reputation: 1034
I have not used the audio recording classes of android much before, so i dont really have much knowledge in the area.
I have written a little app that will record audio in the background, and then play in back, all in the PCM format (i am doing some tests to see how much battery the microphone uses in the background). But when i try and run my play() method, i get the logcat errors:
11-03 00:20:05.744 18248-18248/com.bacon.corey.audiotimeshift E/android.media.AudioTrack﹕ Front channels must be present in multichannel configurations
11-03 00:20:05.748 18248-18248/com.bacon.corey.audiotimeshift E/AudioTrack﹕ Playback Failed
I have googled the errors, but i cant seem to find anything what so ever about them.
If someone wouldnt mind giving me a few pointers, i would be hugely grateful.
This is the code for the application (it is quite sloppy and unfinished, as it is only for testing battery life):
public class MainActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment())
.commit();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
public PlaceholderFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
return rootView;
}
}
public void play(View view) {
Toast.makeText(this, "play", Toast.LENGTH_SHORT).show();
// Get the file we want to playback.
File file = new File(Environment.getExternalStorageDirectory() + File.separator + "ACS.pcm");
// Get the length of the audio stored in the file (16 bit so 2 bytes per short)
// and create a short array to store the recorded audio.
int musicLength = (int)(file.length()/2);
short[] music = new short[musicLength];
try {
// Create a DataInputStream to read the audio data back from the saved file.
InputStream is = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(is);
DataInputStream dis = new DataInputStream(bis);
// Read the file into the music array.
int i = 0;
while (dis.available() > 0) {
music[musicLength-1-i] = dis.readShort();
i++;
}
// Close the input streams.
dis.close();
// Create a new AudioTrack object using the same parameters as the AudioRecord
// object used to create the file.
AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
11025,
AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT,
musicLength,
AudioTrack.MODE_STREAM);
// Start playback
audioTrack.play();
// Write the music buffer to the AudioTrack object
audioTrack.write(music, 0, musicLength);
} catch (Throwable t) {
Log.e("AudioTrack","Playback Failed");
}
}
public void record(View view){
Toast.makeText(this, "record", Toast.LENGTH_SHORT).show();
Log.v("ACS", "OnCreate called");
Intent intent = new Intent(this, ACS.class);
startService(intent);
}
public void stop(View view){
Toast.makeText(this, "stop", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(this, ACS.class);
stopService(intent);
}
}
And
public class ACS extends IntentService {
AudioRecord audioRecord;
public ACS() {
super("ACS");
}
@Override
protected void onHandleIntent(Intent intent) {
Log.v("ACS", "ACS called");
record();
}
public void record() {
Log.v("ACS", "Record started");
int frequency = 11025;
int channelConfiguration = AudioFormat.CHANNEL_IN_MONO;
int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;
File file = new File(Environment.getExternalStorageDirectory() + File.separator + "ACS.pcm");
// Delete any previous recording.
if (file.exists())
file.delete();
// Create the new file.
try {
file.createNewFile();
} catch (IOException e) {
throw new IllegalStateException("Failed to create " + file.toString());
}
try {
// Create a DataOuputStream to write the audio data into the saved file.
OutputStream os = new FileOutputStream(file);
BufferedOutputStream bos = new BufferedOutputStream(os);
DataOutputStream dos = new DataOutputStream(bos);
// Create a new AudioRecord object to record the audio.
int bufferSize = AudioRecord.getMinBufferSize(frequency, channelConfiguration, audioEncoding);
audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,
frequency, channelConfiguration,
audioEncoding, bufferSize);
short[] buffer = new short[bufferSize];
audioRecord.startRecording();
while (audioRecord.getRecordingState() == audioRecord.RECORDSTATE_RECORDING) {
int bufferReadResult = audioRecord.read(buffer, 0, bufferSize);
for (int i = 0; i < bufferReadResult; i++)
dos.writeShort(buffer[i]);
}
audioRecord.stop();
dos.close();
} catch (Throwable t) {
Log.e("AudioRecord", "Recording Failed");
}
Log.v("ACS", "Record stopped");
}
public void onDestroy(){
audioRecord.stop();
Log.v("ACS", "onDestroy called, Record stopped");
}
}
Thanks in advance
Corey :)
Upvotes: 3
Views: 3035
Reputation: 305
A mono audio file needs to be sent to both left and right speaker. Do a logical OR to set this routing:
final int frontPair = AudioFormat.CHANNEL_OUT_FRONT_LEFT | AudioFormat.CHANNEL_OUT_FRONT_RIGHT;
AudioFormat audioFormat = new AudioFormat.Builder()
.setEncoding(AudioFormat.ENCODING_PCM_8BIT)
.setSampleRate(audioSamplingRate)
.setChannelMask(frontPair)
.build();
Upvotes: 0
Reputation: 51
I have the same error message "android.media.AudioTrack﹕ Front channels must be present in multichannel configurations".
When I change the audio settings from AudioFormat.CHANNEL_OUT_MONO to AudioFormat.CHANNEL_IN_MONO, the error messages disappeared. (Or you can try different configuration, like AudioFormat.CHANNEL_IN_STEREO)
AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
11025,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT,
musicLength,
AudioTrack.MODE_STREAM);
But I don't know why this happened. Hope this help.
Upvotes: 1