bool section_is_complete(WaveformActor* actor, Section* section) { int max = MIN(waveform_get_n_audio_blocks(waveform), MAX_BLOCKS_PER_TEXTURE); int i;for(i=0;i<max;i++){ if(!section->ready[i]) return false; } dbg(1, "complete"); return section->completed = true; }
static void v_lo_new_gl2(WaveformActor* actor) { Waveform* waveform = actor->waveform; WaveformPriv* w = waveform->priv; Renderer* renderer = modes[MODE_V_LOW].renderer; int n_blocks = w->num_peaks / (WF_MED_TO_V_LOW * WF_TEXTURE_VISIBLE_SIZE) + ((w->num_peaks % (WF_MED_TO_V_LOW * WF_TEXTURE_VISIBLE_SIZE)) ? 1 : 0); HiResNGWaveform** data = (HiResNGWaveform**)&w->render_data[MODE_V_LOW]; if(!*data){ int n_sections = waveform_get_n_audio_blocks(waveform) / MAX_BLOCKS_PER_TEXTURE + (waveform_get_n_audio_blocks(waveform) % MAX_BLOCKS_PER_TEXTURE ? 1 : 0); *(*data = g_malloc0(sizeof(HiResNGWaveform) + sizeof(Section) * n_sections)) = (HiResNGWaveform){ .n_blocks = n_blocks, .size = n_sections }; g_object_weak_ref((GObject*)waveform, ng_gl2_finalize_notify, renderer); g_hash_table_insert(((NGRenderer*)renderer)->ng_data, waveform, *data); }
inline void med_peakbuf_to_texture(Renderer* renderer, WaveformActor* actor, int b, Section* section, int n_chans, int block_size) { // borders: source data is not blocked so borders are added here. Waveform* waveform = actor->waveform; WaveformPriv* w = waveform->priv; WfPeakBuf* peak = &w->peak; int _b = b % MAX_BLOCKS_PER_TEXTURE; int mm_level = 0; int* lod_max = ((NGRenderer*)renderer)->mmidx_max; int* lod_min = ((NGRenderer*)renderer)->mmidx_min; int stop = (b == waveform_get_n_audio_blocks(waveform) - 1) ? peak->size / WF_PEAK_VALUES_PER_SAMPLE + TEX_BORDER - WF_TEXTURE_VISIBLE_SIZE * b : WF_PEAK_TEXTURE_SIZE; int c; for(c=0;c<n_chans;c++){ int src = WF_PEAK_VALUES_PER_SAMPLE * (b * WF_TEXTURE_VISIBLE_SIZE - TEX_BORDER); int dest = _b * block_size + (c * block_size / 2); int t = 0; if(b == 0){ for(t=0;t<TEX_BORDER;t++){ ng_gl2_set_(section, dest + lod_max[mm_level] + t, 0); ng_gl2_set_(section, dest + lod_min[mm_level] + t, 0); } src = 0; } for(; t<stop; t++, src+=2){ ng_gl2_set_(section, dest + lod_max[mm_level] + t, short_to_char( peak->buf[c][src ])); ng_gl2_set_(section, dest + lod_min[mm_level] + t, short_to_char(-peak->buf[c][src + 1])); } other_lods(renderer, section, dest); } }
static void ng_gl2_load_block (Renderer* renderer, WaveformActor* actor, int b) { NGRenderer* ng_renderer = (NGRenderer*)renderer; Waveform* waveform = actor->waveform; WaveformPriv* w = waveform->priv; #define get_block_size(ACTOR) (modes[renderer->mode].texture_size * waveform_get_n_channels(ACTOR->waveform) * WF_PEAK_VALUES_PER_SAMPLE * ROWS_PER_PEAK_TYPE) Section* add_section(Renderer* renderer, WaveformActor* actor, HiResNGWaveform* data, int s) { int block_size = get_block_size(actor); int buffer_size = block_size * MIN(MAX_BLOCKS_PER_TEXTURE, waveform_get_n_audio_blocks(waveform) - s * MAX_BLOCKS_PER_TEXTURE); dbg(1, "%s %i block_size=%ik section->buffer=%ik", modes[renderer->mode].name, s, block_size / 1024, buffer_size / 1024); Section* section = &data->section[s]; section->buffer = g_malloc0(section->buffer_size = buffer_size); section->time_stamp = ((NGRenderer*)renderer)->time_stamp++; ng_gl2_queue_clean(renderer); return section; }
/* * Load a single audio block for the case where the audio is on a local filesystem. * For thread-safety, the Waveform is not modified. */ gboolean waveform_load_audio_block(Waveform* waveform, WfBuf16* buf16, int block_num) { //TODO handle split stereo files g_return_val_if_fail(waveform, false); // which parts of the audio file are present? // tier 1: 0, 128 // tier 2: 0, 64, 128, 196 // tier 3: 0, 32, 64, 96, 128, ... 196 // tier 4: 0, 16, ... // tier 5: 0, 8, ... // tier 6: 0, 4, ... // tier 7: 0, 2, ... // tier 8: 0, 1, ... //guint n_peaks = ((n_frames * 1 ) / WF_PEAK_RATIO) << audio->n_tiers_present; //int spacing = WF_PEAK_RATIO >> (audio->n_tiers_present - 1); uint64_t start_pos = block_num * (WF_PEAK_BLOCK_SIZE - 2.0 * TEX_BORDER * 256.0); uint64_t end_pos = start_pos + WF_PEAK_BLOCK_SIZE; int n_chans = waveform_get_n_channels(waveform); g_return_val_if_fail(n_chans, false); SF_INFO sfinfo; SNDFILE* sffile; sfinfo.format = 0; if(!(sffile = sf_open(waveform->filename, SFM_READ, &sfinfo))){ gwarn ("not able to open input file %s.", waveform->filename); puts(sf_strerror(NULL)); return false; } if(start_pos > sfinfo.frames){ gerr("startpos too high. %Li > %Li block=%i", start_pos, sfinfo.frames, block_num); return false; } if(end_pos > sfinfo.frames){ dbg(1, "*** last block: end_pos=%Lu max=%Lu", end_pos, sfinfo.frames); end_pos = sfinfo.frames; } sf_seek(sffile, start_pos, SEEK_SET); dbg(1, "block=%s%i%s (%i/%i) start=%Li end=%Li", wf_bold, block_num, wf_white, block_num+1, waveform_get_n_audio_blocks(waveform), start_pos, end_pos); sf_count_t n_frames = MIN(buf16->size, end_pos - start_pos); //1st of these isnt needed? g_return_val_if_fail(buf16 && buf16->buf[WF_LEFT], false); #ifdef WF_DEBUG buf16->start_frame = start_pos; #endif gboolean sf_read_float_to_short(SNDFILE* sffile, WfBuf16* buf, int ch, sf_count_t n_frames) { float readbuf[buf->size]; sf_count_t readcount; if((readcount = sf_readf_float(sffile, readbuf, n_frames)) < n_frames){ gwarn("unexpected EOF: %s", waveform->filename); gwarn(" start_frame=%Li n_frames=%Lu/%Lu read=%Li", start_pos, n_frames, sfinfo.frames, readcount); return false; } //convert to short int j; for(j=0;j<readcount;j++){ buf->buf[ch][j] = readbuf[j] * (1 << 15); } return true; }