void mtx_copy(float32_t eps) { float32_t errf; ambix_matrix_t *left=NULL, *right=NULL; unsigned int i; float32_t maxeps=eps; STARTTEST("\n"); right=ambix_matrix_copy(left, NULL); fail_if((NULL!=right), __LINE__, "copying from NULL matrix erroneously succeeded"); left=ambix_matrix_create(); fail_if((left !=ambix_matrix_init(4, 3, left )), __LINE__, "initializing left matrix failed"); ambix_matrix_fill_data(left, leftdata_4_3); right=ambix_matrix_copy(left, NULL); fail_if((NULL==right), __LINE__, "copying to NULL matrix failed"); errf=matrix_diff(__LINE__, left, right, eps); fail_if(errf>0.f, __LINE__, "diffing mtx with copy0 returned %g (>%g)", errf, 0.f); right=ambix_matrix_copy(left, right); fail_if((NULL==right), __LINE__, "copying to right matrix failed"); errf=matrix_diff(__LINE__, left, right, eps); fail_if(errf>0.f, __LINE__, "diffing mtx with copy returned %g (>%g)", errf, 0.f); ambix_matrix_destroy(left); ambix_matrix_destroy(right); STOPTEST("\n"); }
ambix_err_t ambix_set_adaptormatrix (ambix_t*ambix, const ambix_matrix_t*matrix) { if(0) { } else if((ambix->filemode & AMBIX_READ ) && (AMBIX_BASIC == ambix->info.fileformat)) { ambix_matrix_t*mtx=NULL; /* multiply the matrix with the previous adaptor matrix */ if(AMBIX_EXTENDED == ambix->realinfo.fileformat) { mtx=ambix_matrix_multiply(matrix, &ambix->matrix, &ambix->matrix2); if(mtx != &ambix->matrix2) return AMBIX_ERR_UNKNOWN; ambix->use_matrix=2; return AMBIX_ERR_SUCCESS; } else { if(matrix->cols != ambix->realinfo.ambichannels) { return AMBIX_ERR_INVALID_DIMENSION; } mtx=ambix_matrix_copy(matrix, &ambix->matrix2); ambix->use_matrix=2; } } else if((ambix->filemode & AMBIX_WRITE) && (AMBIX_EXTENDED == ambix->info.fileformat)) { /* too late, writing started already */ if(ambix->startedWriting) return AMBIX_ERR_UNKNOWN; /* check whether the matrix will expand to a full set */ if(!ambix_is_fullset(matrix->rows)) return AMBIX_ERR_INVALID_DIMENSION; if(!ambix_matrix_copy(matrix, &ambix->matrix)) return AMBIX_ERR_UNKNOWN; /* ready to write it to file */ ambix->pendingHeaders=1; return AMBIX_ERR_SUCCESS; } return AMBIX_ERR_UNKNOWN; }
ambix_matrix_t* ambix_matrix_fill(ambix_matrix_t*matrix, ambix_matrixtype_t typ) { int32_t rows=matrix->rows; int32_t cols=matrix->cols; int32_t r, c; float32_t**mtx=matrix->data; ambix_matrix_t*result=NULL; switch(typ) { default: return NULL; case (AMBIX_MATRIX_ZERO): for(r=0; r<rows; r++) { for(c=0; c<cols; c++) mtx[r][c]=0.; } break; case (AMBIX_MATRIX_ONE): for(r=0; r<rows; r++) { for(c=0; c<cols; c++) mtx[r][c]=1.; } break; case (AMBIX_MATRIX_IDENTITY): for(r=0; r<rows; r++) { for(c=0; c<cols; c++) mtx[r][c]=(float32_t)((r==c)?1.:0.); } break; case (AMBIX_MATRIX_FUMA): /* Furse Malham -> ACN/SN3D */ result=_matrix_fuma2ambix(cols); if(!result) return NULL; matrix=ambix_matrix_copy(result, matrix); break; case (AMBIX_MATRIX_TO_FUMA): /* Furse Malham -> ACN/SN3D */ result=_matrix_ambix2fuma(rows); if(!result) return NULL; matrix=ambix_matrix_copy(result, matrix); break; case (AMBIX_MATRIX_SID): /* SID -> ACN */ { float32_t*ordering=(float32_t*)malloc(rows*sizeof(float32_t)); if(!ordering) return NULL; if(!_matrix_sid2acn(ordering, rows)) { free(ordering); return NULL; } matrix=_matrix_router(matrix, ordering, rows, 0); free(ordering); } break; case (AMBIX_MATRIX_TO_SID): /* ACN -> SID */ { float32_t*ordering=(float32_t*)malloc(rows*sizeof(float32_t)); if(!_matrix_sid2acn(ordering, rows)) { free(ordering); return NULL; } matrix=_matrix_router(matrix, ordering, rows, 1); free(ordering); } break; case (AMBIX_MATRIX_N3D): /* N3D -> SN3D */ { float32_t*weights=NULL, *w_=NULL; int32_t counter=0; int32_t o=0, order=ambix_channels2order(rows); if(order<0) return NULL; weights=(float32_t*)malloc(rows*sizeof(float32_t)); w_=weights; for(o=0; o<=order; o++) { const float32_t w=(float32_t)(1./sqrt(2.*o+1.)); int32_t i; for(i=0; i<(2*o+1); i++) { *w_++=w; counter++; } } matrix=_matrix_diag(matrix, weights, rows); free(weights); } break; case (AMBIX_MATRIX_TO_N3D): /* SN3D -> N3D */ { float32_t*weights=NULL, *w_=NULL; int32_t counter=0; int32_t o, order=ambix_channels2order(rows); if(order<0) return NULL; weights=(float32_t*)malloc(rows*sizeof(float32_t)); w_=weights; for(o=0; o<=order; o++) { const float32_t w=(float32_t)(sqrt(2.*o+1.)); int32_t i; for(i=0; i<(2*o+1); i++) { *w_++=w; counter++; } } matrix=_matrix_diag(matrix, weights, rows); free(weights); } break; } if(result) ambix_matrix_destroy(result); return matrix; }
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); }