TileIndex Channel::split_tile_if_needed(TileIndex ti, Tile &tile) { TileIndex new_root_index = TileIndex::null(); if (tile.binary_length() <= m_max_tile_size) return new_root_index; Tile children[2]; TileIndex child_indexes[2]; if (verbosity) log_f("split_tile_if_needed: splitting tile %s", ti.to_string().c_str()); // If we're splitting an "all" tile, it means that until now the channel has only had one tile's worth of // data, and that a proper root tile location couldn't be selected. Select a new root tile now. if (ti.is_nonnegative_all()) { // TODO: this breaks if all samples are at one time ti = new_root_index = TileIndex::index_containing(Range(tile.first_sample_time(), tile.last_sample_time())); if (verbosity) log_f("split_tile_if_needed: Moving root tile to %s", ti.to_string().c_str()); } child_indexes[0]= ti.left_child(); child_indexes[1]= ti.right_child(); double split_time = ti.right_child().start_time(); split_samples(tile.double_samples, split_time, children[0], children[1]); split_samples(tile.string_samples, split_time, children[0], children[1]); for (int i = 0; i < 2; i++) { assert(!has_tile(child_indexes[i])); assert(split_tile_if_needed(child_indexes[i], children[i]) == TileIndex::null()); write_tile(child_indexes[i], children[i]); } create_parent_tile_from_children(ti, tile, children); return new_root_index; }
static void *ambix_write_child_main(void *zz) { t_ambix_write *x = (t_ambix_write*)zz; ambix_t*ambix=NULL; pthread_mutex_lock(&x->x_mutex); while (1) { if (x->x_requestcode == REQUEST_NOTHING) { pthread_cond_signal(&x->x_answercondition); pthread_cond_wait(&x->x_requestcondition, &x->x_mutex); } else if (x->x_requestcode == REQUEST_OPEN) { int sysrtn, writeframes; ambix_info_t ainfo; /* copy file stuff out of the data structure so we can relinquish the mutex while we're in open_soundfile(). */ int64_t onsetframes = x->x_onsetframes; ambix_fileformat_t fileformat = x->x_fileformat; ambix_sampleformat_t sampleformat = x->x_sampleformat; uint32_t ambichannels = x->x_ambichannels; uint32_t xtrachannels = x->x_extrachannels; int localfifosize = x->x_fifosize; float32_t*ambibuf = NULL; float32_t*xtrabuf = NULL; double samplerate = x->x_samplerate; ambix_matrix_t*matrix=NULL; char *filename = strndup(x->x_filename, MAXPDSTRING); if(x->x_matrix) matrix=ambix_matrix_copy(x->x_matrix, matrix); /* alter the request code so that an ensuing "open" will get noticed. */ x->x_requestcode = REQUEST_BUSY; x->x_fileerror = 0; /* open the soundfile with the mutex unlocked */ pthread_mutex_unlock(&x->x_mutex); memset(&ainfo, 0, sizeof(ainfo)); ainfo.fileformat=fileformat; ainfo.ambichannels=ambichannels; ainfo.extrachannels=xtrachannels; ainfo.samplerate=samplerate; ainfo.sampleformat=sampleformat; /* if there's already a file open, close it. This should never happen since ambix_write_open() calls stop if needed and then waits until we're idle. */ if (ambix) ambix_close(ambix); ambix=ambix_open(filename, AMBIX_WRITE, &ainfo); free(filename); if(matrix) { if(ambix) ambix_set_adaptormatrix(ambix, matrix); ambix_matrix_destroy(matrix); matrix=NULL; } if(ambix && onsetframes) { ambix_seek(ambix, onsetframes, SEEK_SET); } if(ambix) { ambibuf = (float32_t*)calloc(localfifosize*ambichannels, sizeof(float32_t)); xtrabuf = (float32_t*)calloc(localfifosize*xtrachannels, sizeof(float32_t)); } pthread_mutex_lock(&x->x_mutex); if(NULL==ambix) { x->x_eof = 1; x->x_fileerror = errno; x->x_requestcode = REQUEST_NOTHING; continue; } /* check if another request has been made; if so, field it */ if (x->x_requestcode != REQUEST_BUSY) continue; x->x_fifotail = 0; /* in a loop, wait for the fifo to have data and write it to disk */ while (x->x_requestcode == REQUEST_BUSY || (x->x_requestcode == REQUEST_CLOSE && x->x_fifohead != x->x_fifotail)) { int fifosize = x->x_fifosize, fifotail; t_sample*buf = x->x_buf; /* if the head is < the tail, we can immediately write from tail to end of fifo to disk; otherwise we hold off writing until there are at least WRITESIZE bytes in the buffer */ if (x->x_fifohead < x->x_fifotail || x->x_fifohead >= x->x_fifotail + WRITFRAMES || (x->x_requestcode == REQUEST_CLOSE && x->x_fifohead != x->x_fifotail)) { writeframes = (x->x_fifohead < x->x_fifotail ? fifosize : x->x_fifohead) - x->x_fifotail; if (writeframes > READFRAMES) writeframes = READFRAMES; } else { pthread_cond_signal(&x->x_answercondition); pthread_cond_wait(&x->x_requestcondition, &x->x_mutex); continue; } fifotail = x->x_fifotail; pthread_mutex_unlock(&x->x_mutex); if(localfifosize<fifosize) { free(ambibuf); free(xtrabuf); localfifosize=fifosize; ambibuf = (float32_t*)calloc(localfifosize*ambichannels, sizeof(float32_t)); xtrabuf = (float32_t*)calloc(localfifosize*xtrachannels, sizeof(float32_t)); } split_samples(buf+fifotail*(ambichannels+xtrachannels), writeframes, ambibuf, ambichannels, xtrabuf, xtrachannels); sysrtn = ambix_writef_float32(ambix, ambibuf, xtrabuf, writeframes); pthread_mutex_lock(&x->x_mutex); if (x->x_requestcode != REQUEST_BUSY && x->x_requestcode != REQUEST_CLOSE) break; if (sysrtn < writeframes) { x->x_fileerror = errno; break; } else { x->x_fifotail += sysrtn; if (x->x_fifotail == fifosize) x->x_fifotail = 0; } /* signal parent in case it's waiting for data */ pthread_cond_signal(&x->x_answercondition); } free(ambibuf);free(xtrabuf); } else if (x->x_requestcode == REQUEST_CLOSE || x->x_requestcode == REQUEST_QUIT) { int quit = (x->x_requestcode == REQUEST_QUIT); if (ambix) { pthread_mutex_unlock(&x->x_mutex); ambix_close(ambix); ambix=NULL; pthread_mutex_lock(&x->x_mutex); } x->x_requestcode = REQUEST_NOTHING; pthread_cond_signal(&x->x_answercondition); if (quit) break; } else { } } pthread_mutex_unlock(&x->x_mutex); return (0); }