int AudioStream_Ogg::getLength(const std::string &path) { if (openal_is_shutdown) return 0; int result; mPath = std::string(path.c_str()); mIsValid = true; #ifdef ANDROID mInfo = AndroidGetAssetFD(path.c_str()); oggFile = fdopen(mInfo.fd, "rb"); fseek(oggFile, mInfo.offset, 0); ov_callbacks callbacks; callbacks.read_func = &nme::AudioStream_Ogg::read_func; callbacks.seek_func = &nme::AudioStream_Ogg::seek_func; callbacks.close_func = &nme::AudioStream_Ogg::close_func; callbacks.tell_func = &nme::AudioStream_Ogg::tell_func; #else oggFile = fopen(path.c_str(), "rb"); #endif if(!oggFile) { //throw std::string("Could not open Ogg file."); LOG_SOUND("Could not open Ogg file."); mIsValid = false; return 0; } oggStream = new OggVorbis_File(); #ifdef ANDROID result = ov_open_callbacks(this, oggStream, NULL, 0, callbacks); #else result = ov_open(oggFile, oggStream, NULL, 0); #endif if(result < 0) { fclose(oggFile); oggFile = 0; //throw std::string("Could not open Ogg stream. ") + errorString(result); LOG_SOUND("Could not open Ogg stream."); //LOG_SOUND(errorString(result).c_str()); mIsValid = false; return 0; } return ov_time_total(oggStream, -1); }
void x1_010_device::device_start() { int i; m_base_clock = clock(); m_rate = clock() / 512; for( i = 0; i < SETA_NUM_CHANNELS; i++ ) { m_smp_offset[i] = 0; m_env_offset[i] = 0; } /* Print some more debug info */ LOG_SOUND(("masterclock = %d rate = %d\n", clock(), m_rate )); /* get stream channels */ m_stream = machine().sound().stream_alloc(*this, 0, 2, m_rate); save_item(NAME(m_rate)); save_item(NAME(m_sound_enable)); save_item(NAME(m_reg)); save_item(NAME(m_HI_WORD_BUF)); save_item(NAME(m_smp_offset)); save_item(NAME(m_env_offset)); save_item(NAME(m_base_clock)); }
bool loadOggSampleFromFile(const char *inFileURL, QuickVec<unsigned char> &outBuffer, int *channels, int *bitsPerSample, int* outSampleRate) { FILE *f; //Read the file data #ifdef ANDROID FileInfo info = AndroidGetAssetFD(inFileURL); f = fdopen(info.fd, "rb"); fseek(f, info.offset, 0); #else f = fopen(inFileURL, "rb"); #endif if (!f) { LOG_SOUND("FAILED to read sound file, file pointer as null?\n"); return false; } OggVorbis_File oggFile; //Read the file data #ifdef ANDROID ov_open(f, &oggFile, NULL, info.length); #else ov_open(f, &oggFile, NULL, 0); #endif return loadOggSample(oggFile, outBuffer, channels, bitsPerSample, outSampleRate); }
bool loadOggSample(OggVorbis_File &oggFile, QuickVec<unsigned char> &outBuffer, int *channels, int *bitsPerSample, int* outSampleRate) { // 0 for Little-Endian, 1 for Big-Endian #ifdef HXCPP_BIG_ENDIAN #define BUFFER_READ_TYPE 1 #else #define BUFFER_READ_TYPE 0 #endif int bitStream; long bytes = 1; int totalBytes = 0; #define BUFFER_SIZE 32768 //Get the file information //vorbis data vorbis_info *pInfo = ov_info(&oggFile, -1); //Make sure this is a valid file if (pInfo == NULL) { LOG_SOUND("FAILED TO READ OGG SOUND INFO, IS THIS EVEN AN OGG FILE?\n"); return false; } //The number of channels *channels = pInfo->channels; //default to 16? todo *bitsPerSample = 16; //Return the same rate as well *outSampleRate = pInfo->rate; // Seem to need four times the read PCM total outBuffer.resize(ov_pcm_total(&oggFile, -1)*4); while (bytes > 0) { if (outBuffer.size() < totalBytes + BUFFER_SIZE) { outBuffer.resize(totalBytes + BUFFER_SIZE); } // Read up to a buffer's worth of decoded sound data bytes = ov_read(&oggFile, (char*)outBuffer.begin() + totalBytes, BUFFER_SIZE, BUFFER_READ_TYPE, 2, 1, &bitStream); totalBytes += bytes; } outBuffer.resize(totalBytes); ov_clear(&oggFile); #undef BUFFER_SIZE #undef BUFFER_READ_TYPE return true; }
void AudioStream_Ogg::check() { if (openal_is_shutdown) return; int error = alGetError(); if(error != AL_NO_ERROR) { //todo : print meaningful errors instead LOG_SOUND("OpenAL error was raised: %d\n", error); mIsValid = false; //throw std::string("OpenAL error was raised."); } } //check
bool loadOggSample(OggVorbis_File &oggFile, QuickVec<unsigned char> &outBuffer, int *channels, int *bitsPerSample, int* outSampleRate) { // 0 for Little-Endian, 1 for Big-Endian int endian = 0; int bitStream; long bytes = 1; #define BUFFER_SIZE 32768 char array[BUFFER_SIZE]; //Get the file information //vorbis data vorbis_info *pInfo = ov_info(&oggFile, -1); //Make sure this is a valid file if (pInfo == NULL) { LOG_SOUND("FAILED TO READ OGG SOUND INFO, IS THIS EVEN AN OGG FILE?\n"); return false; } //The number of channels *channels = pInfo->channels; //default to 16? todo *bitsPerSample = 16; //Return the same rate as well *outSampleRate = pInfo->rate; while (bytes > 0) { // Read up to a buffer's worth of decoded sound data bytes = ov_read(&oggFile, array, BUFFER_SIZE, endian, 2, 1, &bitStream); // Append to end of buffer outBuffer.InsertAt(outBuffer.size(), (unsigned char*)array, bytes); } ov_clear(&oggFile); #undef BUFFER_SIZE return true; }
bool WAV::Decode (Resource *resource, AudioBuffer *audioBuffer) { WAVE_Format wave_format; RIFF_Header riff_header; WAVE_Data wave_data; unsigned char* data; FILE_HANDLE *file = NULL; if (resource->path) { file = lime::fopen (resource->path, "rb"); if (!file) { return false; } int result = lime::fread (&riff_header, sizeof (RIFF_Header), 1, file); if ((riff_header.chunkID[0] != 'R' || riff_header.chunkID[1] != 'I' || riff_header.chunkID[2] != 'F' || riff_header.chunkID[3] != 'F') || (riff_header.format[0] != 'W' || riff_header.format[1] != 'A' || riff_header.format[2] != 'V' || riff_header.format[3] != 'E')) { lime::fclose (file); return false; } long int currentHead = 0; bool foundFormat = false; while (!foundFormat) { currentHead = lime::ftell (file); result = lime::fread (&wave_format, sizeof (WAVE_Format), 1, file); if (result != 1) { LOG_SOUND ("Invalid Wave Format!\n"); lime::fclose (file); return false; } if (wave_format.subChunkID[0] != 'f' || wave_format.subChunkID[1] != 'm' || wave_format.subChunkID[2] != 't' || wave_format.subChunkID[3] != ' ') { lime::fseek (file, wave_format.subChunkSize, SEEK_CUR); } else { foundFormat = true; } } bool foundData = false; while (!foundData) { currentHead = lime::ftell (file); result = lime::fread (&wave_data, sizeof (WAVE_Data), 1, file); if (result != 1) { LOG_SOUND ("Invalid Wav Data Header!\n"); lime::fclose (file); return false; } if (wave_data.subChunkID[0] != 'd' || wave_data.subChunkID[1] != 'a' || wave_data.subChunkID[2] != 't' || wave_data.subChunkID[3] != 'a') { lime::fseek (file, currentHead + sizeof (WAVE_Data) + wave_data.subChunkSize, SEEK_SET); } else { foundData = true; } } audioBuffer->data = new Bytes (wave_data.subChunkSize); audioBuffer->length = wave_data.subChunkSize; if (!lime::fread (audioBuffer->data->Data (), wave_data.subChunkSize, 1, file)) { LOG_SOUND ("error loading WAVE data into struct!\n"); lime::fclose (file); return false; } lime::fclose (file); } else { const char* start = (const char*)resource->data->Data (); const char* end = start + resource->data->Length (); const char* ptr = start; memcpy (&riff_header, ptr, sizeof (RIFF_Header)); ptr += sizeof (RIFF_Header); if ((riff_header.chunkID[0] != 'R' || riff_header.chunkID[1] != 'I' || riff_header.chunkID[2] != 'F' || riff_header.chunkID[3] != 'F') || (riff_header.format[0] != 'W' || riff_header.format[1] != 'A' || riff_header.format[2] != 'V' || riff_header.format[3] != 'E')) { return false; } ptr = find_chunk (ptr, end, "fmt "); if (!ptr) { return false; } readStruct (wave_format, ptr); if (wave_format.subChunkID[0] != 'f' || wave_format.subChunkID[1] != 'm' || wave_format.subChunkID[2] != 't' || wave_format.subChunkID[3] != ' ') { LOG_SOUND ("Invalid Wave Format!\n"); return false; } ptr = find_chunk (ptr, end, "data"); if (!ptr) { return false; } const char* base = readStruct (wave_data, ptr); if (wave_data.subChunkID[0] != 'd' || wave_data.subChunkID[1] != 'a' || wave_data.subChunkID[2] != 't' || wave_data.subChunkID[3] != 'a') { LOG_SOUND ("Invalid Wav Data Header!\n"); return false; } audioBuffer->data->Resize (wave_data.subChunkSize); size_t size = wave_data.subChunkSize; if (size > (end - base)) { return false; } unsigned char* bytes = audioBuffer->data->Data (); memcpy (bytes, base, size); } audioBuffer->sampleRate = (int)wave_format.sampleRate; audioBuffer->channels = wave_format.numChannels; audioBuffer->bitsPerSample = wave_format.bitsPerSample; return true; }
bool loadWavSampleFromFile(const char *inFileURL, QuickVec<unsigned char> &outBuffer, int *channels, int *bitsPerSample, int* outSampleRate) { //http://www.dunsanyinteractive.com/blogs/oliver/?p=72 //Local Declarations FILE* f = NULL; WAVE_Format wave_format; RIFF_Header riff_header; WAVE_Data wave_data; unsigned char* data; #ifdef ANDROID FileInfo info = AndroidGetAssetFD(inFileURL); f = fdopen(info.fd, "rb"); fseek(f, info.offset, 0); #else f = fopen(inFileURL, "rb"); #endif if (!f) { LOG_SOUND("FAILED to read sound file, file pointer as null?\n"); return false; } // Read in the first chunk into the struct fread(&riff_header, sizeof(RIFF_Header), 1, f); //check for RIFF and WAVE tag in memeory if ((riff_header.chunkID[0] != 'R' || riff_header.chunkID[1] != 'I' || riff_header.chunkID[2] != 'F' || riff_header.chunkID[3] != 'F') || (riff_header.format[0] != 'W' || riff_header.format[1] != 'A' || riff_header.format[2] != 'V' || riff_header.format[3] != 'E')) { LOG_SOUND("Invalid RIFF or WAVE Header!\n"); return false; } //Read in the 2nd chunk for the wave info fread(&wave_format, sizeof(WAVE_Format), 1, f); //check for fmt tag in memory if (wave_format.subChunkID[0] != 'f' || wave_format.subChunkID[1] != 'm' || wave_format.subChunkID[2] != 't' || wave_format.subChunkID[3] != ' ') { LOG_SOUND("Invalid Wave Format!\n"); return false; } //check for extra parameters; if (wave_format.subChunkSize > 16) { fseek(f, sizeof(short), SEEK_CUR); } //Read in the the last byte of data before the sound file fread(&wave_data, sizeof(WAVE_Data), 1, f); //check for data tag in memory if (wave_data.subChunkID[0] != 'd' || wave_data.subChunkID[1] != 'a' || wave_data.subChunkID[2] != 't' || wave_data.subChunkID[3] != 'a') { LOG_SOUND("Invalid Wav Data Header!\n"); return false; } //Allocate memory for data data = new unsigned char[wave_data.subChunkSize]; // Read in the sound data into the soundData variable if (!fread(data, wave_data.subChunkSize, 1, f)) { LOG_SOUND("error loading WAVE data into struct!\n"); return false; } //Store in the outbuffer outBuffer.Set(data, wave_data.subChunkSize); //Now we set the variables that we passed in with the //data from the structs *outSampleRate = (int)wave_format.sampleRate; //The format is worked out by looking at the number of //channels and the bits per sample. *channels = wave_format.numChannels; *bitsPerSample = wave_format.bitsPerSample; //clean up and return true if successful fclose(f); delete[] data; return true; }
bool loadWavSampleFromBytes(const float *inData, int len, QuickVec<unsigned char> &outBuffer, int *channels, int *bitsPerSample, int* outSampleRate) { const char* start = (const char*)inData; const char* end = start + len; const char* ptr = start; WAVE_Format wave_format; RIFF_Header riff_header; WAVE_Data wave_data; unsigned char* data; // Read in the first chunk into the struct memcpy(&riff_header, ptr, sizeof(RIFF_Header)); ptr += sizeof(RIFF_Header); //check for RIFF and WAVE tag in memeory if ((riff_header.chunkID[0] != 'R' || riff_header.chunkID[1] != 'I' || riff_header.chunkID[2] != 'F' || riff_header.chunkID[3] != 'F') || (riff_header.format[0] != 'W' || riff_header.format[1] != 'A' || riff_header.format[2] != 'V' || riff_header.format[3] != 'E')) { LOG_SOUND("Invalid RIFF or WAVE Header!\n"); return false; } //Read in the 2nd chunk for the wave info ptr = find_chunk(ptr, end, "fmt "); if (!ptr) { return false; } readStruct(wave_format, ptr); //check for fmt tag in memory if (wave_format.subChunkID[0] != 'f' || wave_format.subChunkID[1] != 'm' || wave_format.subChunkID[2] != 't' || wave_format.subChunkID[3] != ' ') { LOG_SOUND("Invalid Wave Format!\n"); return false; } ptr = find_chunk(ptr, end, "data"); if (!ptr) { return false; } const char* base = readStruct(wave_data, ptr); //check for data tag in memory if (wave_data.subChunkID[0] != 'd' || wave_data.subChunkID[1] != 'a' || wave_data.subChunkID[2] != 't' || wave_data.subChunkID[3] != 'a') { LOG_SOUND("Invalid Wav Data Header!\n"); return false; } //Allocate memory for data //data = new unsigned char[wave_data.subChunk2Size]; // Read in the sound data into the soundData variable size_t size = wave_data.subChunkSize; if (size > (end - base)) { return false; } /*mlChannels = wave_format.numChannels; if (mlChannels == 2) { if (wave_format.bitsPerSample == 8) { mFormat = AL_FORMAT_STEREO8; mlSamples = size / 2; } else //if (wave_format.bitsPerSample == 16) { mlSamples = size / 4; mFormat = AL_FORMAT_STEREO16; } } else //if (mlChannels == 1) { if (wave_format.bitsPerSample == 8) { mlSamples = size; mFormat = AL_FORMAT_MONO8; } else //if (wave_format.bitsPerSample == 16) { mlSamples = size / 2; mFormat = AL_FORMAT_MONO16; } } mlFrequency = wave_format.sampleRate; mfTotalTime = float(mlSamples) / float(mlFrequency);*/ //Store in the outbuffer outBuffer.Set((unsigned char*)base, size); //Now we set the variables that we passed in with the //data from the structs *outSampleRate = (int)wave_format.sampleRate; //The format is worked out by looking at the number of //channels and the bits per sample. *channels = wave_format.numChannels; *bitsPerSample = wave_format.bitsPerSample; //clean up and return true if successful //fclose(f); //delete[] data; return true; }
bool open(const std::string &path, int startTime) { int result; mPath = std::string(path.c_str()); mIsValid = true; #ifdef ANDROID mInfo = AndroidGetAssetFD(path.c_str()); oggFile = fdopen(mInfo.fd, "rb"); fseek(oggFile, mInfo.offset, 0); ov_callbacks callbacks; callbacks.read_func = &nme::AudioStream_Ogg::read_func; callbacks.seek_func = &nme::AudioStream_Ogg::seek_func; callbacks.close_func = &nme::AudioStream_Ogg::close_func; callbacks.tell_func = &nme::AudioStream_Ogg::tell_func; #else oggFile = fopen(path.c_str(), "rb"); #endif if(!oggFile) { //throw std::string("Could not open Ogg file."); LOG_SOUND("Could not open Ogg file."); mIsValid = false; return false; } oggStream = new OggVorbis_File(); #ifdef ANDROID result = ov_open_callbacks(this, oggStream, NULL, 0, callbacks); #else result = ov_open(oggFile, oggStream, NULL, 0); #endif if(result < 0) { fclose(oggFile); oggFile = 0; //throw std::string("Could not open Ogg stream. ") + errorString(result); LOG_SOUND("Could not open Ogg stream."); //LOG_SOUND(errorString(result).c_str()); mIsValid = false; return false; } vorbisInfo = ov_info(oggStream, -1); vorbisComment = ov_comment(oggStream, -1); mChannels = vorbisInfo->channels; mRate = vorbisInfo->rate; if (startTime != 0) { double seek = startTime * 0.001; ov_time_seek(oggStream, seek); } return true; }
void AudioStream_Ogg::open(const std::string &path, int startTime, int inLoops, const SoundTransform &inTransform) { if (openal_is_shutdown) return; int result; mPath = std::string(path.c_str()); mStartTime = startTime; mLoops = inLoops; mIsValid = true; mSuspend = false; #ifdef ANDROID mInfo = AndroidGetAssetFD(path.c_str()); oggFile = fdopen(mInfo.fd, "rb"); fseek(oggFile, mInfo.offset, 0); ov_callbacks callbacks; callbacks.read_func = &nme::AudioStream_Ogg::read_func; callbacks.seek_func = &nme::AudioStream_Ogg::seek_func; callbacks.close_func = &nme::AudioStream_Ogg::close_func; callbacks.tell_func = &nme::AudioStream_Ogg::tell_func; #else oggFile = fopen(path.c_str(), "rb"); #endif if(!oggFile) { //throw std::string("Could not open Ogg file."); LOG_SOUND("Could not open Ogg file."); mIsValid = false; return; } oggStream = new OggVorbis_File(); #ifdef ANDROID result = ov_open_callbacks(this, oggStream, NULL, 0, callbacks); #else result = ov_open(oggFile, oggStream, NULL, 0); #endif if(result < 0) { fclose(oggFile); oggFile = 0; //throw std::string("Could not open Ogg stream. ") + errorString(result); LOG_SOUND("Could not open Ogg stream."); //LOG_SOUND(errorString(result).c_str()); mIsValid = false; return; } vorbisInfo = ov_info(oggStream, -1); vorbisComment = ov_comment(oggStream, -1); if(vorbisInfo->channels == 1) { format = AL_FORMAT_MONO16; } else { format = AL_FORMAT_STEREO16; } if (startTime != 0) { double seek = startTime * 0.001; ov_time_seek(oggStream, seek); } alGenBuffers(2, buffers); check(); alGenSources(1, &source); check(); alSource3f(source, AL_POSITION, 0.0, 0.0, 0.0); alSource3f(source, AL_VELOCITY, 0.0, 0.0, 0.0); alSource3f(source, AL_DIRECTION, 0.0, 0.0, 0.0); alSourcef (source, AL_ROLLOFF_FACTOR, 0.0 ); alSourcei (source, AL_SOURCE_RELATIVE, AL_TRUE ); setTransform(inTransform); } //open
OpenALSound::OpenALSound(float *inData, int len) { IncRef(); mBufferID = 0; mIsStream = false; QuickVec<uint8> buffer; int _channels; int _bitsPerSample; ALenum format; ALsizei freq; bool ok = false; //Determine the file format before we try anything AudioFormat type = Audio::determineFormatFromBytes(inData, len); switch(type) { case eAF_ogg: ok = Audio::loadOggSampleFromBytes(inData, len, buffer, &_channels, &_bitsPerSample, &freq ); break; case eAF_wav: ok = Audio::loadWavSampleFromBytes(inData, len, buffer, &_channels, &_bitsPerSample, &freq ); break; default: LOG_SOUND("Error opening sound file, unsupported type.\n"); } //Work out the format from the data if (_channels == 1) { if (_bitsPerSample == 8 ) { format = AL_FORMAT_MONO8; } else if (_bitsPerSample == 16) { format = (int)AL_FORMAT_MONO16; } } else if (_channels == 2) { if (_bitsPerSample == 8 ) { format = (int)AL_FORMAT_STEREO8; } else if (_bitsPerSample == 16) { format = (int)AL_FORMAT_STEREO16; } } //channels = 2 if (!ok) { LOG_SOUND("Error opening sound data\n"); mError = "Error opening sound data"; } else if (alGetError() != AL_NO_ERROR) { LOG_SOUND("Error after opening sound data\n"); mError = "Error after opening sound data"; } else { // grab a buffer ID from openAL alGenBuffers(1, &mBufferID); // load the awaiting data blob into the openAL buffer. alBufferData(mBufferID,format,&buffer[0],buffer.size(),freq); // once we have all our information loaded, get some extra flags alGetBufferi(mBufferID, AL_SIZE, &bufferSize); alGetBufferi(mBufferID, AL_FREQUENCY, &frequency); alGetBufferi(mBufferID, AL_CHANNELS, &channels); alGetBufferi(mBufferID, AL_BITS, &bitsPerSample); } }
OpenALSound::OpenALSound(const std::string &inFilename, bool inForceMusic) { IncRef(); mBufferID = 0; mIsStream = false; mTotalTime = -1; #ifdef HX_MACOS char fileURL[1024]; GetBundleFilename(inFilename.c_str(),fileURL,1024); #else #ifdef IPHONE std::string asset = GetResourcePath() + gAssetBase + inFilename; const char *fileURL = asset.c_str(); #else const char *fileURL = inFilename.c_str(); #endif #endif if (!fileURL) { //LOG_SOUND("OpenALSound constructor() error in url"); mError = "Error int url: " + inFilename; } else { QuickVec<uint8> buffer; int _channels; int _bitsPerSample; ALenum format; ALsizei freq; bool ok = false; //Determine the file format before we try anything AudioFormat type = Audio::determineFormatFromFile(std::string(fileURL)); switch(type) { case eAF_ogg: if (inForceMusic) { mIsStream = true; mStreamPath = fileURL; } else { ok = Audio::loadOggSampleFromFile( fileURL, buffer, &_channels, &_bitsPerSample, &freq ); } break; case eAF_wav: ok = Audio::loadWavSampleFromFile( fileURL, buffer, &_channels, &_bitsPerSample, &freq ); break; default: LOG_SOUND("Error opening sound file, unsupported type.\n"); } if (mIsStream) return; //Work out the format from the data if (_channels == 1) { if (_bitsPerSample == 8 ) { format = AL_FORMAT_MONO8; } else if (_bitsPerSample == 16) { format = (int)AL_FORMAT_MONO16; } } else if (_channels == 2) { if (_bitsPerSample == 8 ) { format = (int)AL_FORMAT_STEREO8; } else if (_bitsPerSample == 16) { format = (int)AL_FORMAT_STEREO16; } } //channels = 2 if (!ok) { LOG_SOUND("Error opening sound data\n"); mError = "Error opening sound data"; } else if (alGetError() != AL_NO_ERROR) { LOG_SOUND("Error after opening sound data\n"); mError = "Error after opening sound data"; } else { // grab a buffer ID from openAL alGenBuffers(1, &mBufferID); // load the awaiting data blob into the openAL buffer. alBufferData(mBufferID,format,&buffer[0],buffer.size(),freq); // once we have all our information loaded, get some extra flags alGetBufferi(mBufferID, AL_SIZE, &bufferSize); alGetBufferi(mBufferID, AL_FREQUENCY, &frequency); alGetBufferi(mBufferID, AL_CHANNELS, &channels); alGetBufferi(mBufferID, AL_BITS, &bitsPerSample); } //!ok } }