Surface *Surface::Load(const OSChar *inFilename) { FILE *file = OpenRead(inFilename); if (!file) { #ifdef ANDROID ByteArray bytes = AndroidGetAssetBytes(inFilename); if (bytes.Ok()) { Surface *result = LoadFromBytes(bytes.Bytes(), bytes.Size()); return result; } #endif return 0; } Surface *result = TryJPEG(file,0,0); if (!result) { rewind(file); result = TryPNG(file,0,0); } fclose(file); return result; }
value lime_byte_array_overwrite_file (value inFilename, value inBytes) { // file is created if it doesn't exist, // if it exists, it is truncated to zero FILE_HANDLE *file = lime::fopen (val_os_string (inFilename), "wb"); if (!file) { #ifdef ANDROID // [todo] #endif return alloc_null(); } ByteArray array (inBytes); // The function fwrite() writes nitems objects, each size bytes long, to the // stream pointed to by stream, obtaining them from the location given by // ptr. // fwrite(const void *restrict ptr, size_t size, size_t nitems, FILE *restrict stream); lime::fwrite (array.Bytes (), 1, array.Size (), file); lime::fclose (file); return alloc_null (); }
void FillBuffer(const ByteArray &inBytes) { int time_samples = inBytes.Size()/sizeof(float)/STEREO_SAMPLES; const float *buffer = (const float *)inBytes.Bytes(); enum { MASK = BUF_SIZE - 1 }; for(int i=0;i<time_samples;i++) { int mono_pos = (i+mDynamicFillPos) & MASK; mDynamicBuffer[ mono_pos<<1 ] = *buffer++ * ((1<<15)-1); mDynamicBuffer[ (mono_pos<<1) + 1 ] = *buffer++ * ((1<<15)-1); } if (mDynamicFillPos<(sSoundPos-mDynamicStartPos)) ELOG("Too slow - FillBuffer %d / %d)", mDynamicFillPos, (sSoundPos-mDynamicStartPos) ); mDynamicFillPos += time_samples; if (time_samples<1024 && !mDynamicDone) { mDynamicDone = true; for(int i=0;i<2048;i++) { int mono_pos = (i+mDynamicFillPos) & MASK; mDynamicBuffer[ mono_pos<<1 ] = 0; mDynamicBuffer[ (mono_pos<<1) + 1 ] = 0; } int samples_left = (int)mDynamicFillPos - (int)(sSoundPos-mDynamicStartPos); int ticks_left = samples_left*1000/44100; //printf("Expire in %d (%d)\n", samples_left, ticks_left ); #ifndef EMSCRIPTEN Mix_ExpireChannel(mChannel, ticks_left>0 ? ticks_left : 1 ); #endif } }
Sound *Sound::Create(const std::string &inFilename,bool inForceMusic) { //Always check if openal is intitialized if (!OpenALInit()) return 0; //Return a reference OpenALSound *sound; #ifdef ANDROID if (!inForceMusic) { ByteArray bytes = AndroidGetAssetBytes(inFilename.c_str()); sound = new OpenALSound((float*)bytes.Bytes(), bytes.Size()); } else { sound = new OpenALSound(inFilename, inForceMusic); } #else sound = new OpenALSound(inFilename, inForceMusic); #endif if (sound->ok ()) return sound; else return 0; }
value lime_al_buffer_data (value buffer, value format, value data, value size, value freq) { ByteArray byteArray (data); //int arraySize = byteArray.Size (); const float *bytes = (float *)byteArray.Bytes (); //int elements = arraySize / sizeof (float); int count = val_int (size); alBufferData (val_int (buffer), val_int (format), bytes, count, val_int (freq)); return alloc_null (); }
value lime_byte_array_get_native_pointer (value inByteArray) { ByteArray bytes (inByteArray); if (!val_is_null (bytes.mValue)) { return alloc_float ((intptr_t)bytes.Bytes ()); } return alloc_null (); }
static int sGetFile(const char *inFilename, unsigned char **outBuf) { #ifdef ANDROID ByteArray bytes = AndroidGetAssetBytes(inFilename); #else ByteArray bytes = ByteArray::FromFile(inFilename); #endif ELOG("Loaded cert %s %d bytes.", inFilename, bytes.Size()); if (bytes.Size()>0) { *outBuf = (unsigned char *)malloc(bytes.Size()); memcpy(*outBuf,bytes.Bytes(),bytes.Size()); return bytes.Size(); } return -1; }
void OpenALChannel::QueueBuffer(ALuint inBuffer, const ByteArray &inBytes) { int time_samples = inBytes.Size()/sizeof(float)/STEREO_SAMPLES; const float *buffer = (const float *)inBytes.Bytes(); for(int i=0;i<time_samples;i++) { mSampleBuffer[ i<<1 ] = *buffer++ * ((1<<15)-1); mSampleBuffer[ (i<<1) + 1 ] = *buffer++ * ((1<<15)-1); } mDynamicDone = time_samples < 1024; alBufferData(inBuffer, AL_FORMAT_STEREO16, mSampleBuffer, time_samples*STEREO_SAMPLES*sizeof(short), 44100 ); //LOG_SOUND("Dynamic queue buffer %d (%d)", inBuffer, time_samples ); alSourceQueueBuffers(mSourceID, 1, &inBuffer ); }
Surface *Surface::Load(const OSChar *inFilename) { FILE *file = OpenRead(inFilename); if (!file) { #ifdef ANDROID ByteArray bytes = AndroidGetAssetBytes(inFilename); if (bytes.Ok()) { Surface *result = LoadFromBytes(bytes.Bytes(), bytes.Size()); return result; } #endif return 0; } int len = 0; while(inFilename[len]) len++; bool jpegFirst = false; bool pngFirst = false; if (len>4) { // Jpeg/jpg if (inFilename[len-4]=='j' || inFilename[len-4]=='J' || inFilename[len-3]=='j' || inFilename[len-4]=='J' ) jpegFirst = true; else if (inFilename[len-3]=='p' || inFilename[len-3]=='P' ) pngFirst = true; } Surface *result = 0; if (jpegFirst) { result = TryJPEG(file,0,0); if (!result) { rewind(file); result = TryPNG(file,0,0); } } else if (pngFirst) { result = TryPNG(file,0,0); if (!result) { rewind(file); result = TryJPEG(file,0,0); } } else { uint8 first = 0; fread(&first,1,1,file); if (first==0xff) { rewind(file); result = TryJPEG(file,0,0); } else if (first==0x89) { rewind(file); result = TryPNG(file,0,0); } } fclose(file); return result; }
bool OGG::Decode (Resource *resource, AudioBuffer *audioBuffer) { OggVorbis_File oggFile; if (resource->path) { FILE_HANDLE *file = lime::fopen (resource->path, "rb"); if (!file) { return false; } if (file->isFile ()) { ov_open (file->getFile (), &oggFile, NULL, file->getLength ()); } else { ByteArray data = ByteArray (resource->path); OAL_OggMemoryFile fakeFile = { data.Bytes (), data.Size (), 0 }; if (ov_open_callbacks (&fakeFile, &oggFile, NULL, 0, OAL_CALLBACKS_BUFFER) != 0) { return false; } } } else { OAL_OggMemoryFile fakeFile = { resource->data->Bytes (), resource->data->Size (), 0 }; if (ov_open_callbacks (&fakeFile, &oggFile, NULL, 0, OAL_CALLBACKS_BUFFER) != 0) { return false; } } // 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 vorbis_info *pInfo = ov_info (&oggFile, -1); if (pInfo == NULL) { //LOG_SOUND("FAILED TO READ OGG SOUND INFO, IS THIS EVEN AN OGG FILE?\n"); return false; } audioBuffer->channels = pInfo->channels; audioBuffer->sampleRate = pInfo->rate; //default to 16? todo audioBuffer->bitsPerSample = 16; // Seem to need four times the read PCM total audioBuffer->data->Resize (ov_pcm_total (&oggFile, -1) * 4); while (bytes > 0) { if (audioBuffer->data->Size () < totalBytes + BUFFER_SIZE) { audioBuffer->data->Resize (totalBytes + BUFFER_SIZE); } bytes = ov_read (&oggFile, (char *)audioBuffer->data->Bytes () + totalBytes, BUFFER_SIZE, BUFFER_READ_TYPE, 2, 1, &bitStream); totalBytes += bytes; } audioBuffer->data->Resize (totalBytes); ov_clear (&oggFile); #undef BUFFER_SIZE #undef BUFFER_READ_TYPE return true; }
bool JPEG::Decode (Resource *resource, ImageBuffer* imageBuffer, bool decodeData) { struct jpeg_decompress_struct cinfo; //struct jpeg_error_mgr jerr; //cinfo.err = jpeg_std_error (&jerr); struct ErrorData jpegError; cinfo.err = jpeg_std_error (&jpegError.base); jpegError.base.error_exit = OnError; jpegError.base.output_message = OnOutput; FILE_HANDLE *file = NULL; if (resource->path) { file = lime::fopen (resource->path, "rb"); if (!file) { return false; } } if (setjmp (jpegError.on_error)) { if (file) { lime::fclose (file); } jpeg_destroy_decompress (&cinfo); return false; } jpeg_create_decompress (&cinfo); if (file) { if (file->isFile ()) { jpeg_stdio_src (&cinfo, file->getFile ()); } else { ByteArray data = ByteArray (resource->path); MySrcManager manager (data.Bytes (), data.Size ()); cinfo.src = &manager.pub; } } else { MySrcManager manager (resource->data->Bytes (), resource->data->Size ()); cinfo.src = &manager.pub; } bool decoded = false; if (jpeg_read_header (&cinfo, TRUE) == JPEG_HEADER_OK) { cinfo.out_color_space = JCS_RGB; if (decodeData) { jpeg_start_decompress (&cinfo); int components = cinfo.num_components; imageBuffer->Resize (cinfo.output_width, cinfo.output_height); unsigned char *bytes = imageBuffer->data->Bytes (); unsigned char *scanline = new unsigned char [imageBuffer->width * imageBuffer->height * components]; while (cinfo.output_scanline < cinfo.output_height) { jpeg_read_scanlines (&cinfo, &scanline, 1); // convert 24-bit scanline to 32-bit const unsigned char *line = scanline; const unsigned char *const end = line + imageBuffer->width * components; while (line != end) { *bytes++ = *line++; *bytes++ = *line++; *bytes++ = *line++; *bytes++ = 0xFF; } } delete[] scanline; jpeg_finish_decompress (&cinfo); } else { imageBuffer->width = cinfo.image_width; imageBuffer->height = cinfo.image_height; } decoded = true; } if (file) { lime::fclose (file); } jpeg_destroy_decompress (&cinfo); return decoded; }
bool PNG::Decode (Resource *resource, ImageBuffer *imageBuffer) { unsigned char png_sig[PNG_SIG_SIZE]; png_structp png_ptr; png_infop info_ptr; png_uint_32 width, height; int bit_depth, color_type, interlace_type; FILE_HANDLE *file = NULL; if (resource->path) { file = lime::fopen (resource->path, "rb"); if (!file) return false; int read = lime::fread (png_sig, PNG_SIG_SIZE, 1, file); if (png_sig_cmp (png_sig, 0, PNG_SIG_SIZE)) { lime::fclose (file); return false; } } else { memcpy (png_sig, resource->data->Bytes (), PNG_SIG_SIZE); if (png_sig_cmp (png_sig, 0, PNG_SIG_SIZE)) { return false; } } if ((png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)) == NULL) { if (file) lime::fclose (file); return false; } if ((info_ptr = png_create_info_struct (png_ptr)) == NULL) { png_destroy_read_struct (&png_ptr, (png_infopp)NULL, (png_infopp)NULL); if (file) lime::fclose (file); return false; } // sets the point which libpng will jump back to in the case of an error if (setjmp (png_jmpbuf (png_ptr))) { png_destroy_read_struct (&png_ptr, &info_ptr, (png_infopp)NULL); if (file) lime::fclose (file); return false; } if (file) { if (file->isFile ()) { png_init_io (png_ptr, file->getFile ()); png_set_sig_bytes (png_ptr, PNG_SIG_SIZE); } else { ByteArray data = ByteArray (resource->path); ReadBuffer buffer (data.Bytes (), data.Size ()); png_set_read_fn (png_ptr, &buffer, user_read_data_fn); } } else { ReadBuffer buffer (resource->data->Bytes (), resource->data->Size ()); png_set_read_fn (png_ptr, &buffer, user_read_data_fn); } png_read_info (png_ptr, info_ptr); png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL); //bool has_alpha = (color_type == PNG_COLOR_TYPE_GRAY_ALPHA || color_type == PNG_COLOR_TYPE_RGB_ALPHA || png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS)); png_set_expand (png_ptr); png_set_filler (png_ptr, 0xff, PNG_FILLER_AFTER); //png_set_gray_1_2_4_to_8 (png_ptr); png_set_palette_to_rgb (png_ptr); png_set_gray_to_rgb (png_ptr); if (bit_depth < 8) { png_set_packing (png_ptr); } else if (bit_depth == 16) { png_set_scale_16 (png_ptr); } //png_set_bgr (png_ptr); int bpp = 4; const unsigned int stride = width * bpp; imageBuffer->Resize (width, height, bpp); unsigned char *bytes = imageBuffer->data->Bytes (); int number_of_passes = png_set_interlace_handling (png_ptr); for (int pass = 0; pass < number_of_passes; pass++) { for (int i = 0; i < height; i++) { png_bytep anAddr = (png_bytep)(bytes + i * stride); png_read_rows (png_ptr, (png_bytepp) &anAddr, NULL, 1); } } png_read_end (png_ptr, NULL); png_destroy_read_struct (&png_ptr, &info_ptr, (png_infopp)NULL); if (file) lime::fclose (file); return true; }