//bpp == the resulting bits per pixel //bpp == the source image bits per pixel //req_bpp == use this instead of the source bool load_info( QuickVec<unsigned char> &out_buffer, const char* _id, int* w, int* h, int* bpp, int* bpp_source, int req_bpp = 4 ) { //get a io file pointer to the image snow::io::iosrc* src = snow::io::iosrc_from_file(_id, "rb"); if(!src) { snow::log(1, "/ snow / cannot open image file from %s", _id); return false; } //always use callbacks because we use snow abstracted IO stbi_io_callbacks stbi_snow_callbacks = { snow_stbi_read, snow_stbi_skip, snow_stbi_eof }; unsigned char *data = stbi_load_from_callbacks(&stbi_snow_callbacks, src, w, h, bpp_source, req_bpp); //we are done with the src snow::io::close(src); snow::log(2, "/ snow / image / w:%d h:%d source bpp:%d bpp:%d\n", *w, *h, *bpp_source, req_bpp); if(data != NULL) { int _w = *w; int _h = *h; int _bpp = *bpp_source; //if a requested bpp was given, override it if(req_bpp != 0) { _bpp = req_bpp; } //actual used bpp *bpp = _bpp; //work out the total length of the buffer unsigned int length = _w * _h * _bpp; //store it out_buffer.Set(data, length); //clean up used memory stbi_image_free(data); } else { //data != NULL snow::log(1, "/ snow / image unable to be loaded by snow: %s reason: %s", _id, stbi_failure_reason()); return false; } return true; } //load_info
//bpp == the resulting bits per pixel //bpp == the source image bits per pixel //req_bpp == use this instead of the source bool info_from_bytes( QuickVec<unsigned char> &out_buffer, const unsigned char* bytes, int byteOffset, int byteLength, const char* _id, int *w, int *h, int* bpp, int* bpp_source, int req_bpp = 4 ) { //get a io file pointer to the image snow::io::iosrc* src = snow::io::iosrc_from_mem( (void*)(bytes + byteOffset), byteLength ); if(!src) { snow::log(1, "/ snow / cannot open bytes from %s", _id); return false; } //always use callbacks because we use snow abstracted IO stbi_io_callbacks stbi_snow_callbacks = { snow_stbi_read, snow_stbi_skip, snow_stbi_eof }; unsigned char *data = stbi_load_from_callbacks(&stbi_snow_callbacks, src, w, h, bpp_source, req_bpp); //we are done with the src snow::io::close(src); snow::log(2, "/ snow / image / w:%d h:%d source bpp:%d bpp:%d\n", *w, *h, *bpp_source, req_bpp); if(data != NULL) { int _w = *w; int _h = *h; int _bpp = *bpp_source; //if a requested bpp was given, override it if(req_bpp != 0) { _bpp = req_bpp; } //actual used bpp *bpp = _bpp; //work out the total length of the output buffer unsigned int length = _w * _h * _bpp; //store it out_buffer.Set(data, length); //clean up used memory stbi_image_free(data); } //data != NULL return true; } //info_from_bytes
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; }