下面三种方式前两种区别不大,缺点是必须要等到系统加载差不多了才可以使用。Android系统启动时间很长,想要早点播放的话可以选择第三种,tinyalsa播放。

一. AudioTrack

    auto lpTrack = new AudioTrack();
    status_t status = lpTrack->set(
            AUDIO_STREAM_MUSIC,
            24000,
            AUDIO_FORMAT_PCM_16_BIT,
            AUDIO_CHANNEL_OUT_MONO,
            0,  
            AUDIO_OUTPUT_FLAG_FAST,
            audioCallback, this, //callback callback
            0,  
            0,  
            true,
            AUDIO_SESSION_ALLOCATE, //sessionId
            AudioTrack::TRANSFER_SYNC);
    if (status != NO_ERROR) {
        ALOGE("Error %d initializing AudioTrack", status);
        return;
    }
    
   	lpTrack->stop();
    lpTrack->start();
    while(offset < pcm_out_length){
        written = lpTrack->write(pcm_out + offset, pcm_out_length - offset);
        offset += written;
        ALOGE("%s written %d, offset %d, pcm_out %d", __FUNCTION__, written, offset, pcm_out_length);
        if(written < 0) break;
    }
  


final String TEST_NAME = "testPlaybackHeadPositionAfterFlush";
final int TEST_SR = 22050;
final int TEST_CONF = AudioFormat.CHANNEL_OUT_STEREO;
final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
final int TEST_MODE = AudioTrack.MODE_STREAM;
final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
 
//-------- initialization --------------
int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, minBuffSize, TEST_MODE);
byte data[] = new byte[minBuffSize/2];
//--------    test        --------------
track.write(data, 0, data.length);
track.write(data, 0, data.length);
track.play();
Thread.sleep(100);
track.stop();
track.flush();
//-------- tear down      --------------
track.release();

二. MediaPlayer

三. tinyalsa

struct pcm_config config;
struct pcm *pcm;
char *buffer;
unsigned int size, read_sz;
int num_read;
  
memset(&config, 0, sizeof(config));
config.channels = channels;
config.rate = rate;
config.period_size = period_size;
config.period_count = period_count;

config.format = PCM_FORMAT_S16_LE;
config.start_threshold = 0;
config.stop_threshold = 0;
config.silence_threshold = 0;

pcm = pcm_open(card, device, PCM_OUT, &config);
if (!pcm || !pcm_is_ready(pcm)) {
	fprintf(stderr, "Unable to open PCM device %u (%s)\n", device, pcm_get_error(pcm));
	return;
}

size = pcm_frames_to_bytes(pcm, pcm_get_buffer_size(pcm));
buffer = malloc(size);
do {
	read_sz = size < data_sz ? size : data_sz;
	num_read = fread(buffer, 1, read_sz, file);
	if (num_read > 0) {
	if (pcm_write(pcm, buffer, num_read)) {
		fprintf(stderr, "Error playing sample\n");
		break;
	}
	data_sz -= num_read;
} while (!close && num_read > 0 && data_sz > 0);

free(buffer);
pcm_close(pcm);

好像还有第四种,使用openGL ES,这个没怎么研究过。

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐