static ALCboolean opensl_reset_playback(ALCdevice *Device) { osl_data *data = Device->ExtraData; SLDataLocator_AndroidSimpleBufferQueue loc_bufq; SLDataLocator_OutputMix loc_outmix; SLDataFormat_PCM format_pcm; SLDataSource audioSrc; SLDataSink audioSnk; SLInterfaceID id; SLboolean req; SLresult result; SLuint32 sampleRate; Device->FmtChans = DevFmtStereo; Device->FmtType = DevFmtShort; sampleRate = convertSampleRate(Device->Frequency); if(sampleRate == -1) { sampleRate = SL_SAMPLINGRATE_44_1; Device->Frequency = 44100; } SetDefaultWFXChannelOrder(Device); id = SL_IID_ANDROIDSIMPLEBUFFERQUEUE; req = SL_BOOLEAN_TRUE; loc_bufq.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE; loc_bufq.numBuffers = Device->NumUpdates; format_pcm.formatType = SL_DATAFORMAT_PCM; format_pcm.numChannels = ChannelsFromDevFmt(Device->FmtChans); format_pcm.samplesPerSec = sampleRate; format_pcm.bitsPerSample = BytesFromDevFmt(Device->FmtType) * 8; format_pcm.containerSize = format_pcm.bitsPerSample; format_pcm.channelMask = GetChannelMask(Device->FmtChans); format_pcm.endianness = IS_LITTLE_ENDIAN ? SL_BYTEORDER_LITTLEENDIAN : SL_BYTEORDER_BIGENDIAN; audioSrc.pLocator = &loc_bufq; audioSrc.pFormat = &format_pcm; loc_outmix.locatorType = SL_DATALOCATOR_OUTPUTMIX; loc_outmix.outputMix = data->outputMix; audioSnk.pLocator = &loc_outmix; audioSnk.pFormat = NULL; if(data->bufferQueueObject != NULL) SLObjectItf_Destroy(data->bufferQueueObject); data->bufferQueueObject = NULL; result = SLEngineItf_CreateAudioPlayer(data->engine, &data->bufferQueueObject, &audioSrc, &audioSnk, 1, &id, &req); PRINTERR(result, "engine->CreateAudioPlayer"); if(SL_RESULT_SUCCESS == result) { result = SLObjectItf_Realize(data->bufferQueueObject, SL_BOOLEAN_FALSE); PRINTERR(result, "bufferQueue->Realize"); } if(SL_RESULT_SUCCESS != result) { if(data->bufferQueueObject != NULL) SLObjectItf_Destroy(data->bufferQueueObject); data->bufferQueueObject = NULL; return ALC_FALSE; } return ALC_TRUE; }
static int Start(dtaudio_output_t *aout) { SLresult result; aout_sys_t *sys = (aout_sys_t *) aout->ao_priv; dtaudio_para_t *para = &aout->para; // configure audio source - this defines the number of samples you can enqueue. SLDataLocator_AndroidSimpleBufferQueue loc_bufq = { SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, OPENSLES_BUFFERS }; int mask; if (para->dst_channels > 1) mask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT; else mask = SL_SPEAKER_FRONT_CENTER; SLDataFormat_PCM format_pcm; format_pcm.formatType = SL_DATAFORMAT_PCM; format_pcm.numChannels = para->dst_channels; //format_pcm.samplesPerSec = ((SLuint32) para->dst_samplerate * 1000) ; format_pcm.samplesPerSec = ((SLuint32) convertSampleRate(para->dst_samplerate)); format_pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16; format_pcm.containerSize = SL_PCMSAMPLEFORMAT_FIXED_16; format_pcm.channelMask = mask; format_pcm.endianness = SL_BYTEORDER_LITTLEENDIAN; SLDataSource audioSrc = {&loc_bufq, &format_pcm}; // configure audio sink SLDataLocator_OutputMix loc_outmix = { SL_DATALOCATOR_OUTPUTMIX, sys->outputMixObject }; SLDataSink audioSnk = {&loc_outmix, NULL}; //create audio player const SLInterfaceID ids2[] = {sys->SL_IID_ANDROIDSIMPLEBUFFERQUEUE, sys->SL_IID_VOLUME}; static const SLboolean req2[] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE}; result = CreateAudioPlayer(sys->engineEngine, &sys->playerObject, &audioSrc, &audioSnk, sizeof(ids2) / sizeof(*ids2), ids2, req2); if (unlikely(result != SL_RESULT_SUCCESS)) { // error return -1; /* Try again with a more sensible samplerate */ #if 0 fmt->i_rate = 44100; format_pcm.samplesPerSec = ((SLuint32) 44100 * 1000) ; result = CreateAudioPlayer(sys->engineEngine, &sys->playerObject, &audioSrc, &audioSnk, sizeof(ids2) / sizeof(*ids2), ids2, req2); #endif } CHECK_OPENSL_ERROR("Failed to create audio player"); result = Realize(sys->playerObject, SL_BOOLEAN_FALSE); CHECK_OPENSL_ERROR("Failed to realize player object."); result = GetInterface(sys->playerObject, sys->SL_IID_PLAY, &sys->playerPlay); CHECK_OPENSL_ERROR("Failed to get player interface."); result = GetInterface(sys->playerObject, sys->SL_IID_VOLUME, &sys->volumeItf); CHECK_OPENSL_ERROR("failed to get volume interface."); result = GetInterface(sys->playerObject, sys->SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &sys->playerBufferQueue); CHECK_OPENSL_ERROR("Failed to get buff queue interface"); result = RegisterCallback(sys->playerBufferQueue, PlayedCallback, (void *) aout); CHECK_OPENSL_ERROR("Failed to register buff queue callback."); // set the player's state to playing result = SetPlayState(sys->playerPlay, SL_PLAYSTATE_PLAYING); CHECK_OPENSL_ERROR("Failed to switch to playing state"); /* XXX: rounding shouldn't affect us at normal sampling rate */ sys->rate = para->dst_samplerate; sys->samples_per_buf = OPENSLES_BUFLEN * para->dst_samplerate / 1000; sys->buf = malloc(OPENSLES_BUFFERS * sys->samples_per_buf * bytesPerSample(aout)); if (!sys->buf) goto error; sys->started = 0; sys->next_buf = 0; sys->samples = 0; SetPositionUpdatePeriod(sys->playerPlay, AOUT_MIN_PREPARE_TIME * 1000 / CLOCK_FREQ); return 0; error: if (sys->playerObject) { Destroy(sys->playerObject); sys->playerObject = NULL; } return -1; }
/** * Loads the contents of an X-Com CAT file which usually contains * a set of sound files. The CAT starts with an index of the offset * and size of every file contained within. Each file consists of a * filename followed by its contents. * @param filename Filename of the CAT set. * @param wav Are the sounds in WAV format? * @sa http://www.ufopaedia.org/index.php?title=SOUND */ void SoundSet::loadCat(const std::string &filename, bool wav) { // Load CAT file CatFile sndFile (filename.c_str()); if (!sndFile) { throw Exception(filename + " not found"); } // Load each sound file for (int i = 0; i < sndFile.getAmount(); ++i) { // Read WAV chunk unsigned char *sound = (unsigned char*) sndFile.load(i); unsigned int size = sndFile.getObjectSize(i); // If there's no WAV header (44 bytes), add it // Assuming sounds are 6-bit 8000Hz (DOS version) unsigned char *newsound = 0; const int headerSize = 44; if (!wav) { if (size > 5) size -= 5; // skip 5 garbage name bytes at beginning if (size) size--; // omit trailing null byte if (size != 0) { char header[] = {'R', 'I', 'F', 'F', 0x00, 0x00, 0x00, 0x00, 'W', 'A', 'V', 'E', 'f', 'm', 't', ' ', 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x11, 0x2b, 0x00, 0x00, 0x11, 0x2b, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 'd', 'a', 't', 'a', 0x00, 0x00, 0x00, 0x00}; // scale to 8 bits for (unsigned int n = 0; n < size; ++n) sound[5 + n] *= 4; // copy and do the conversion... newsound = new unsigned char[headerSize + size*2]; memcpy(newsound, header, headerSize); memcpy(newsound + headerSize, sound + 5, size); int newsize = convertSampleRate(sound + 5, size, newsound + headerSize); size = newsize + headerSize; // Rewrite the number of samples in the WAV file int headersize = newsize + 36; int soundsize = newsize; memcpy(newsound + 4, &headersize, sizeof(headersize)); memcpy(newsound + 40, &soundsize, sizeof(soundsize)); } } // so it's WAV, but in 8 khz, we have to convert it to 11 khz sound else if (0x40 == sound[0x18] && 0x1F == sound[0x19] && 0x00 == sound[0x1A] && 0x00 == sound[0x1B]) { unsigned char *sound2 = new unsigned char[size*2]; // rewrite the samplerate in the header to 11 khz sound[0x18]=0x11; sound[0x19]=0x2B; sound[0x1C]=0x11; sound[0x1D]=0x2B; // copy and do the conversion... memcpy(sound2, sound, size); int newsize = convertSampleRate(sound + headerSize, size - headerSize, sound2 + headerSize); size = newsize + headerSize; // Rewrite the number of samples in the WAV file memcpy(sound2 + 0x28, &newsize, sizeof(newsize)); // Ok, now replace the original with the converted: delete[] sound; sound = sound2; } Sound *s = new Sound(); try { if (size == 0) { throw Exception("Invalid sound file"); } if (wav) s->load(sound, size); else s->load(newsound, size); } catch (const Exception &) { // Ignore junk in the file } _sounds[i] = s; delete[] sound; if (!wav) { delete[] newsound; } } }