Skip to content

Most visited

Recently visited

navigation

I2S

The Inter-IC Sound (IIS or I2S) bus connects digital audio devices and transfers PCM audio data between them. It is commonly used to connect microphones and audio amplifiers to a host control system.

I2S is a synchronous serial interface, which means it relies on shared clock signals to synchronize data transfer between devices. An I2S master device drives communication and timing through the primary bit clock (BCLK) signal, similar to I2C or SPI. I2S also includes a separate left-right clock (LRCLK) signal, which the master uses to select the proper audio channel for data (left or right).

""

I2S devices contain at least one Serial Data (SD) signal. This is common with peripherals, which generally only produce or consume audio data. Master devices are more likely to have dedicated lines for receive (SDIN) and transmit (SDOUT) to support full-duplex communication. This allows you to connect to multiple peripherals to send and receive audio data simultaneously.

Managing the device connection

In order to open a connection to a particular I2S device, you need to know the unique name of the bus. During the initial stages of development, or when porting an app to new hardware, it's helpful to discover all the available device names from PeripheralManagerService using getI2sDeviceList():

PeripheralManagerService manager = new PeripheralManagerService();
List<String> deviceList = manager.getI2sDeviceList();
if (deviceList.isEmpty()) {
    Log.i(TAG, "No I2S bus available on this device.");
} else {
    Log.i(TAG, "List of available devices: " + deviceList);
}

Once you know the target device name, use PeripheralManagerService to connect to that device and supply the audio parameters of the PCM data. You can provide these as discrete parameters, or as an AudioFormat. When you are done communicating with the peripheral device, close the connection to free up resources. Additionally, you cannot open a new connection to the device until the existing connection is closed. To close the connection, use the device's close() method.

public class HomeActivity extends Activity {
    // I2S Device Name
    private static final String I2S_DEVICE_NAME = ...;

    private static final AudioFormat AUDIO_FORMAT_STEREO =
            new AudioFormat.Builder()
            .setChannelMask(AudioFormat.CHANNEL_IN_STEREO)
            .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
            .setSampleRate(44100)
            .build();

    private I2sDevice mDevice;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Attempt to access the I2C device
        try {
            PeripheralManagerService manager = new PeripheralManagerService();
            mDevice = manager.openI2sDevice(I2S_DEVICE_NAME, AUDIO_FORMAT_STEREO);
        } catch (IOException e) {
            Log.w(TAG, "Unable to access I2S device", e);
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        if (mDevice != null) {
            try {
                mDevice.close();
                mDevice = null;
            } catch (IOException e) {
                Log.w(TAG, "Unable to close I2S device", e);
            }
        }
    }
}

Choosing an audio format

When creating an I2S connection, the supplied audio parameters define the transfer characteristics of the bus, such as the clock frequency. Consider the following example format for 2-channel audio data, 16-bit samples, captured at 44.1kHz:

private static final AudioFormat AUDIO_FORMAT_STEREO =
        new AudioFormat.Builder()
        .setChannelMask(AudioFormat.CHANNEL_IN_STEREO) // 2 channels
        .setEncoding(AudioFormat.ENCODING_PCM_16BIT)   // 16-bit samples
        .setSampleRate(44100)                          // 44.1kHz
        .build();

In addition to describing the expected audio data, this tells the I2S driver the required frequency of the BCLK signal. The frequency is derived from the following formula:

Frequency = SampleRate x Encoding x ChannelCount

Per the formula, the above example format requires an I2S bit clock frequency of 1.41MHz. Similar to the requirements on UART baud rate, the timing of this signal must be very accurate to avoid transmission errors caused by jitter. Ensure that your hardware platform can accurately generate the required bit clock frequency for your chosen format parameters.

To learn more about audio frames, encoding, and sampling, see the AudioFormat reference.

Transferring audio samples

The data transfer methods of I2sDevice mirror the format of the AudioTrack and AudioRecord APIs. This allows your app to integrate with custom audio peripherals the same way it would with the built-in microphone or speaker. Each method accepts data as a byte[], short[], or ByteBuffer. Choose the version that matches the encoding used for your audio data.

The following example reads data from an I2S input device (such as a microphone) and echoes that data out through the default audio route:

public int echoAudio(String i2sName, AudioFormat format) throws IOException {
    // Set up audio input source
    PeripheralManagerService manager = new PeripheralManagerService();
    I2sDevice source = manager.openI2sDevice(i2sName, format);

    // Set up the audio playback sink
    int bufferSize = AudioTrack.getMinBufferSize(
            format.getSampleRate(),
            format.getChannelMask(),
            format.getEncoding());
    AudioTrack sink = new AudioTrack.Builder()
            .setAudioFormat(format)
            .setTransferMode(AudioTrack.MODE_STATIC)
            .setBufferSizeInBytes(bufferSize)
            .build();

    // Transfer data from input to output
    ByteBuffer buffer = ByteBuffer.allocate(bufferSize);
    int read = source.read(buffer, bufferSize);
    sink.write(buffer, read);

    return read;
}
This site uses cookies to store your preferences for site-specific language and display options.

Hooray!

This class requires API level or higher

This doc is hidden because your selected API level for the documentation is . You can change the documentation API level with the selector above the left navigation.

For more information about specifying the API level your app requires, read Supporting Different Platform Versions.

Take a one-minute survey?
Help us improve Android tools and documentation.