qboolean SNDDMA_Init(void) { if ( ! enableSound() ) { return false; } gDMAByteIndex = 0; // Initialize the AudioTrack. status_t result = gAudioTrack.set( AudioSystem::DEFAULT, // stream type SAMPLE_RATE, // sample rate BITS_PER_SAMPLE == 16 ? AudioSystem::PCM_16_BIT : AudioSystem::PCM_8_BIT, // format (8 or 16) (CHANNEL_COUNT > 1) ? AudioSystem::CHANNEL_OUT_STEREO : AudioSystem::CHANNEL_OUT_MONO, // channel mask 0, // default buffer size 0, // flags AndroidQuakeSoundCallback, // callback 0, // user 0); // default notification size LOGI("AudioTrack status = %d (%s)\n", result, result == NO_ERROR ? "success" : "error"); if ( result == NO_ERROR ) { LOGI("AudioTrack latency = %u ms\n", gAudioTrack.latency()); LOGI("AudioTrack format = %u bits\n", gAudioTrack.format() == AudioSystem::PCM_16_BIT ? 16 : 8); LOGI("AudioTrack sample rate = %u Hz\n", gAudioTrack.getSampleRate()); LOGI("AudioTrack frame count = %d\n", int(gAudioTrack.frameCount())); LOGI("AudioTrack channel count = %d\n", gAudioTrack.channelCount()); // Initialize Quake's idea of a DMA buffer. shm = &sn; memset((void*)&sn, 0, sizeof(sn)); shm->splitbuffer = false; // Not used. shm->samplebits = gAudioTrack.format() == AudioSystem::PCM_16_BIT ? 16 : 8; shm->speed = gAudioTrack.getSampleRate(); shm->channels = gAudioTrack.channelCount(); shm->samples = TOTAL_BUFFER_SIZE / BYTES_PER_SAMPLE; shm->samplepos = 0; // Not used. shm->buffer = (unsigned char*) Hunk_AllocName(TOTAL_BUFFER_SIZE, (char*) "shmbuf"); shm->submission_chunk = 1; // Not used. shm->soundalive = true; if ( (shm->samples & 0x1ff) != 0 ) { LOGE("SNDDDMA_Init: samples must be power of two."); return false; } if ( shm->buffer == 0 ) { LOGE("SNDDDMA_Init: Could not allocate sound buffer."); return false; } gAudioTrack.setVolume(1.0f, 1.0f); gAudioTrack.start(); } return result == NO_ERROR; }