void test_push_mode_forever(FILE *g, char *filename) { int p,q, len, error, used; uint8 *data = stb_file(filename, &len); stb_vorbis *v; if (!data) stb_fatal("Couldn't open {%s}", filename); p = 0; q = 1; retry: v = stb_vorbis_open_pushdata(data, q, &used, &error, NULL); if (v == NULL) { if (error == VORBIS_need_more_data) { q += 1; goto retry; } printf("Error %d\n", error); exit(1); } p += used; show_info(v); for(;;) { int k=0; int n; float *left, *right; float **outputs; int num_c; q = 32; retry3: if (q > len-p) q = len-p; used = stb_vorbis_decode_frame_pushdata(v, data+p, q, &num_c, &outputs, &n); if (used == 0) { if (p+q == len) { // seek randomly when at end... this makes sense when listening to it, but dumb when writing to file p = stb_rand(); if (p < 0) p = -p; p %= (len - 8000); stb_vorbis_flush_pushdata(v); q = 128; goto retry3; } if (q < 128) q = 128; q *= 2; goto retry3; } p += used; if (n == 0) continue; left = outputs[0]; right = num_c > 1 ? outputs[1] : outputs[0]; write_floats(g, n, left, right); } stb_vorbis_close(v); }
// in push mode, you can load your data any way you want, then // feed it a little bit at a time. this is the preferred way to // handle reading from a packed file or some custom stream format; // instead of putting callbacks inside stb_vorbis, you just keep // a little buffer (it needs to be big enough for one packet of // audio, except at the beginning where you need to buffer up the // entire header). // // for this test, I just load all the data and just lie to stb_vorbis // and claim I only have a little of it void test_decode_frame_pushdata(FILE *g, char *filename) { int p,q, len, error, used; stb_vorbis *v; uint8 *data = stb_file(filename, &len); if (!data) stb_fatal("Couldn't open {%s}", filename); p = 0; q = 1; retry: v = stb_vorbis_open_pushdata(data, q, &used, &error, NULL); if (v == NULL) { if (error == VORBIS_need_more_data) { q += 1; goto retry; } fprintf(stderr, "Error %d\n", error); exit(1); } p += used; show_info(v); for(;;) { int k=0; int n; float *left, *right; uint32 next_t=0; float **outputs; int num_c; q = 32; retry3: if (q > len-p) q = len-p; used = stb_vorbis_decode_frame_pushdata(v, data+p, q, &num_c, &outputs, &n); if (used == 0) { if (p+q == len) break; // no more data, stop if (q < 128) q = 128; q *= 2; goto retry3; } p += used; if (n == 0) continue; // seek/error recovery left = outputs[0]; right = num_c > 1 ? outputs[1] : outputs[0]; write_floats(g, n, left, right); } stb_vorbis_close(v); }
void render_init(void) { // @TODO: support non-DXT path char **files = stb_readdir_recursive("data", "*.crn"); int i; camera_bounds[0][0] = - 0.75f; camera_bounds[0][1] = - 0.75f; camera_bounds[0][2] = - 4.25f; camera_bounds[1][0] = + 0.75f; camera_bounds[1][1] = + 0.75f; camera_bounds[1][2] = + 0.25f; init_chunk_caches(); init_mesh_building(); init_mesh_build_threads(); s_init_physics_cache(); glGenTextures(2, voxel_tex); glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, voxel_tex[0]); for (i=0; i < 11; ++i) { glTexImage3DEXT(GL_TEXTURE_2D_ARRAY_EXT, i, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 1024>>i,1024>>i,128,0, GL_RGBA,GL_UNSIGNED_BYTE,NULL); } #if 1 for (i=0; i < sizeof(textures)/sizeof(textures[0]); ++i) { size_t len; char *filename = stb_sprintf("data/pixar/crn/%s.crn", textures[i].filename); uint8 *data = stb_file(filename, &len); load_crn_to_texture_array(i, data, len); free(data); texture_scales[i] = 1.0f/4;// textures[i].scale; } #endif // temporary hack: voxel_tex[1] = voxel_tex[0]; init_voxel_render(voxel_tex); { char *frag[] = { dumb_fragment_shader, NULL }; char error[1024]; GLuint fragment; fragment = stbgl_compile_shader(STBGL_FRAGMENT_SHADER, frag, -1, error, sizeof(error)); if (!fragment) { ods("oops"); exit(0); } dumb_prog = stbgl_link_program(0, fragment, NULL, -1, error, sizeof(error)); } #if 0 { size_t len; unsigned char *data = stb_file(files[0], &len); glGenTextures(1, &debug_tex); glBindTexture(GL_TEXTURE_2D, debug_tex); load_crn_to_texture(data, len); free(data); } #endif }