Exemple #1
0
void create_tests(float32_t eps) {
  int rows=4;
  int cols=3;
  int cols2=2;
  ambix_matrix_t matrix, *left, *right;
  STARTTEST("");

  memset(&matrix, 0, sizeof(matrix));

  left=ambix_matrix_create();
  fail_if((left==NULL), __LINE__, "failed to create left matrix");
  fail_if((left->rows || left->cols), __LINE__, "created empty matrix has non-zero size");
  fail_if((left!=ambix_matrix_init(rows, cols, left)), __LINE__, "initializing existing matrix* returned new matrix");
  fail_if((left->rows!=rows || left->cols!=cols), __LINE__, "created matrix [%dx%d] does not match [%dx%d]", left->rows, left->cols, cols, cols2);

  right=ambix_matrix_init(cols, cols2, NULL);
  fail_if((right==NULL), __LINE__, "failed to create right matrix");
  fail_if((right->rows!=cols || right->cols!=cols2), __LINE__, "created matrix [%dx%d] does not match [%dx%d]", right->rows, right->cols, cols, cols2);

  fail_if((&matrix!=ambix_matrix_init(rows, cols2, &matrix)), __LINE__, "initializing existing matrix returned new matrix");
  fail_if((matrix.rows!=rows || matrix.cols!=cols2), __LINE__, "initialized matrix [%dx%d] does not match [%dx%d]", matrix.rows, matrix.cols, rows, cols2);


  ambix_matrix_deinit(&matrix);
  fail_if((matrix.rows || matrix.cols), __LINE__, "deinitialized matrix is non-zero");

  ambix_matrix_deinit(left);
  fail_if((left->rows || left->cols), __LINE__, "deinitialized matrix is non-zero");

  ambix_matrix_destroy(left);
  ambix_matrix_destroy(right);
}
Exemple #2
0
void mtxmul_eye_tests(float32_t eps) {
  float32_t errf;
  ambix_matrix_t *left, *result, *eye;
  STARTTEST("");
  eye=ambix_matrix_init(4, 4, NULL);
  fail_if((eye!=ambix_matrix_fill(eye, AMBIX_MATRIX_IDENTITY)), __LINE__, "filling unity matrix %p did not return original matrix %p", eye);

  left=ambix_matrix_init(4, 2, NULL);
  fail_if(AMBIX_ERR_SUCCESS!=ambix_matrix_fill_data(left, resultdata_4_2), __LINE__,
          "filling left data failed");

  result=ambix_matrix_init(4, 2, NULL);
  fail_if(AMBIX_ERR_SUCCESS!=ambix_matrix_fill_data(result, resultdata_4_2), __LINE__,
          "filling result data failed");

  fail_if((result!=ambix_matrix_multiply(eye, left, result)), __LINE__, "multiplication into matrix did not return original matrix");
#if 0
  matrix_print(eye);
  matrix_print(result);
  matrix_print(left);
#endif
  errf=matrix_diff(__LINE__, left, result, eps);
  fail_if((errf>eps), __LINE__, "diffing matrix M with E*M returned %f (>%f)", errf, eps);

  ambix_matrix_destroy(left);
  ambix_matrix_destroy(result);
  ambix_matrix_destroy(eye);
}
Exemple #3
0
void check_matrix(const char*name, ambix_matrixtype_t typ, uint32_t rows, uint32_t cols) {
  ambix_matrix_t*mtx=NULL;
  ambix_matrix_t*result=NULL;
  ambix_matrix_t*zeros=NULL;
  float32_t errf=0.f;
  float32_t eps=1e-20;

  STARTTEST(name);

  mtx=ambix_matrix_init(rows, cols, mtx);
  result=ambix_matrix_fill(mtx, typ);
  
  fail_if((result==NULL), __LINE__, "matrix_fill returned NULL");
  fail_if((result!=mtx ), __LINE__, "matrix_fill did not return matrix %p (got %p)", mtx, result);

  zeros=ambix_matrix_init(result->rows, result->cols, zeros);
  zeros=ambix_matrix_fill(zeros, AMBIX_MATRIX_ZERO);


  errf=matrix_check_diff(name, result, zeros);

  if(AMBIX_MATRIX_ZERO==typ) {
    fail_if(!(errf<eps), __LINE__, "zero matrix non-zero (%f>%f)", errf, eps);
  } else {
    fail_if((errf<eps), __LINE__, "non-zero matrix zero (%f<%f)", errf, eps);
  }


  ambix_matrix_destroy(mtx);
  ambix_matrix_destroy(zeros); 
}
Exemple #4
0
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");

}
Exemple #5
0
/*
 * calculate the inverse of any (rectangular) real-valued matrix using cholesky decomposition
 */
ambix_matrix_t*
_ambix_matrix_pinvert_cholesky(const ambix_matrix_t*input, ambix_matrix_t*inverse, float32_t tolerance) {
  /* (rows>cols)?(inv(x'*x)*x'):(x'*inv(x*x')) */
  float32_t toler = tolerance;
  ambix_matrix_t*trans = _ambix_matrix_transpose(input, 0);
  ambix_matrix_t*chinv=0;
  ambix_matrix_t*result=0;
  do {
    if(!trans)break;
    if(input->rows > input->cols) {
      chinv=_ambix_matrix_multiply(trans, input, chinv);
      if(!chinv)break;
      _am_cholesky2_decomp(chinv, toler);
      _am_cholesky2_inverse(chinv);
      result=_ambix_matrix_multiply(chinv, trans, inverse);
    } else {
      chinv=_ambix_matrix_multiply(input, trans, chinv);
      if(!chinv)break;
      _am_cholesky2_decomp(chinv, toler);
      _am_cholesky2_inverse(chinv);
      result=_ambix_matrix_multiply(trans, chinv, inverse);
    }
  } while(0);
  if(trans)ambix_matrix_destroy(trans);
  if(chinv)ambix_matrix_destroy(chinv);

  return result;
}
Exemple #6
0
static void ambix_write_free(t_ambix_write *x) {
  /* request QUIT and wait for acknowledge */
  void *threadrtn;
  pthread_mutex_lock(&x->x_mutex);
  x->x_requestcode = REQUEST_QUIT;
  /* post("stopping ambix_write thread..."); */
  pthread_cond_signal(&x->x_requestcondition);
  while (x->x_requestcode != REQUEST_NOTHING) {
    /* post("signalling..."); */
    pthread_cond_signal(&x->x_requestcondition);
    pthread_cond_wait(&x->x_answercondition, &x->x_mutex);
  }
  pthread_mutex_unlock(&x->x_mutex);
  if (pthread_join(x->x_childthread, &threadrtn))
    error("ambix_write_free: join failed");
  /* post("... done."); */

  pthread_cond_destroy(&x->x_requestcondition);
  pthread_cond_destroy(&x->x_answercondition);
  pthread_mutex_destroy(&x->x_mutex);
  freebytes(x->x_buf, x->x_bufsize);

  if(x->x_matrix)
    ambix_matrix_destroy(x->x_matrix);
  x->x_matrix=NULL;
}
Exemple #7
0
void mtxmul_tests(float32_t eps) {
  float32_t errf;
  ambix_matrix_t *left=NULL, *right=NULL, *result, *testresult;
  STARTTEST("\n");

 /* fill in some test data */
  left=ambix_matrix_init(4, 3, NULL);
  ambix_matrix_fill_data(left, leftdata_4_3);
  right=ambix_matrix_init(3, 2, NULL);
  ambix_matrix_fill_data(right, rightdata_3_2);
  testresult=ambix_matrix_init(4, 2, NULL);
  ambix_matrix_fill_data(testresult, resultdata_4_2);

  errf=matrix_diff(__LINE__, left, left, eps);
  fail_if(!(errf<eps), __LINE__, "diffing matrix with itself returned %f (>%f)", errf, eps);

  /* NULL multiplications */
  result=ambix_matrix_multiply(NULL, NULL, NULL);
  fail_if(NULL!=result, __LINE__, "multiplying NULL*NULL returned success");
  result=ambix_matrix_multiply(left, NULL, result);
  fail_if(NULL!=result, __LINE__, "multiplying left*NULL returned success");
  result=ambix_matrix_multiply(NULL, left, result);
  fail_if(NULL!=result, __LINE__, "multiplying NULL*left returned success");

  /* do some matrix multiplication */
  result=ambix_matrix_multiply(left, right, NULL);
  fail_if((NULL==result), __LINE__, "multiply into NULL did not create matrix");

  fail_if((result!=ambix_matrix_multiply(left, right, result)), __LINE__, "multiply into existing matrix returned new matrix");

#if 0
  matrix_print(left);
  matrix_print(right);
  matrix_print(result);
  printf("------------\n");
#endif
  errf=matrix_diff(__LINE__, testresult, result, eps);
  fail_if((errf>eps), __LINE__, "diffing two results of same multiplication returned %f (>%f)", errf, eps);

  ambix_matrix_destroy(left);
  ambix_matrix_destroy(right);
  ambix_matrix_destroy(result);
  ambix_matrix_destroy(testresult);
  STOPTEST("\n");
}
Exemple #8
0
static void mtxinverse_test(const ambix_matrix_t *mtx, const ambix_matrix_t *result, float32_t eps) {
  ambix_matrix_t *pinv = 0;
  ambix_matrix_t *mul=0;
  ambix_matrix_t *eye=0;
  float32_t errf;
  int min_rowcol=(mtx->cols<mtx->rows)?mtx->cols:mtx->rows;

  fail_if((NULL==mtx), __LINE__, "cannot invert NULL-matrix");
  eye=ambix_matrix_init(min_rowcol, min_rowcol, eye);
  eye=ambix_matrix_fill(eye, AMBIX_MATRIX_IDENTITY);
  fail_if((NULL==eye), __LINE__, "cannot create eye-matrix for pinv-verification");

  pinv=ambix_matrix_pinv(mtx, pinv);
  if(NULL==pinv)matrix_print(mtx);
  fail_if((NULL==pinv), __LINE__, "could not invert matrix");

  if(mtx->cols < mtx->rows)
    mul=ambix_matrix_multiply(pinv, mtx, 0);
  else
    mul=ambix_matrix_multiply(mtx, pinv, 0);

#if 0
  matrix_print(mtx);
  matrix_print(pinv);
  matrix_print(mul);
  if(result)matrix_print(result);
  printf("------------\n");
#endif

  if(result) {
    errf=matrix_diff(__LINE__, pinv, result, eps);
    fail_if((errf>eps), __LINE__, "diffing (pseudo)inverse returned %g (>%g)", errf, eps);

    errf=matrix_diff(__LINE__, mul, eye, eps);
    fail_if((errf>eps), __LINE__, "diffing mtx*pinv(mtx) returned %g (>%g)", errf, eps);
  } else {
    errf=matrix_diff(__LINE__, mul, eye, eps);
    fail_if((!(isnan(errf) || isinf(errf) || (errf>eps))), __LINE__, "diffing invalid mtx*pinv(mtx) returned %g (!>%g)", errf, eps);
  }

  ambix_matrix_destroy(pinv);
  ambix_matrix_destroy(mul);
  ambix_matrix_destroy(eye);
}
Exemple #9
0
ambix_matrix_t*inverse_matrices(ambix_matrixtype_t typ, uint32_t rows, uint32_t cols) {
  ambix_matrixtype_t pyt = (ambix_matrixtype_t)(AMBIX_MATRIX_TO_AMBIX | typ);
  ambix_matrix_t*mtx=ambix_matrix_init(rows, cols, NULL);
  ambix_matrix_t*xtm=ambix_matrix_init(cols, rows, NULL);

  ambix_matrix_t*a2f=ambix_matrix_fill(mtx, typ);
  ambix_matrix_t*f2a=ambix_matrix_fill(xtm,  pyt);

  //  ambix_matrix_t*result=ambix_matrix_multiply(a2f, f2a, NULL);
  ambix_matrix_t*result=ambix_matrix_multiply(f2a, a2f, NULL);

  if(a2f!=mtx)
    ambix_matrix_destroy(a2f);
  ambix_matrix_destroy(mtx);

  if(f2a!=xtm)
    ambix_matrix_destroy(f2a);
  ambix_matrix_destroy(xtm);

  return result;
}
Exemple #10
0
void datamul_tests(float32_t eps) {
  float32_t errf;
  float32_t*resultdata  = (float32_t*)calloc(2*4, sizeof(float32_t));
  float32_t*resultdataT = (float32_t*)calloc(4*2, sizeof(float32_t));
  float32_t*inputdata   = (float32_t*)calloc(2*3, sizeof(float32_t));

  fail_if((NULL==resultdata), __LINE__, "couldn't callocate resultdata");
  fail_if((NULL==resultdataT), __LINE__, "couldn't callocate resultdataT");
  fail_if((NULL==inputdata), __LINE__, "couldn't callocate inputdata");

  ambix_matrix_t*mtx=NULL;
  STARTTEST("\n");

  mtx=ambix_matrix_init(4, 3, NULL);
  ambix_matrix_fill_data(mtx, leftdata_4_3);

  data_transpose(inputdata, rightdata_3_2, 3, 2);

  fail_if(AMBIX_ERR_SUCCESS!=ambix_matrix_multiply_float32(resultdata, mtx, inputdata, 2), __LINE__,
          "data multiplication failed");

  data_transpose(resultdataT, resultdata, 2, 4);

  errf=data_diff(__LINE__, FLOAT32, resultdataT, resultdata_4_2, 4*2, eps);
  if(errf>eps) {
    printf("matrix:\n");
    matrix_print(mtx);
    printf("input:\n");
    data_print(FLOAT32, inputdata, 3*2);

    printf("expected:\n");
    data_print(FLOAT32, resultdata_4_2, 4*2);
    printf("calculated:\n");
    data_print(FLOAT32, resultdataT   , 4*2);

  }
  fail_if(!(errf<eps), __LINE__, "diffing data multiplication returned %f (>%f)", errf, eps);

#if 0
  printf("matrix:\n");matrix_print(mtx);
  printf("input :\n");  data_print(FLOAT32, rightdata_3_2, 3*2);
  printf("output:\n");  data_print(FLOAT32, resultdata, 4*2);

  printf("target:\n");  data_print(FLOAT32, resultdata_4_2, 4*2);
#endif


  if(mtx)ambix_matrix_destroy(mtx);
  free(resultdata);
  free(resultdataT);
  free(inputdata);
  STOPTEST("\n");
}
Exemple #11
0
void check_inversion(const char*name, ambix_matrixtype_t typ, uint32_t rows, uint32_t cols) {
  ambix_matrix_t*eye=NULL;
  ambix_matrix_t*result=NULL;
  float32_t errf;
  float32_t eps=1e-6;

  STARTTEST(name);

  result=inverse_matrices(typ, rows, cols);
  eye=ambix_matrix_init(result->rows, result->cols, eye);
  eye=ambix_matrix_fill(eye, AMBIX_MATRIX_IDENTITY);

  errf=matrix_check_diff(name, result, eye);

  if(!(errf<eps)){
    matrix_print(result);
  }

  fail_if(!(errf<eps), __LINE__, "diffing matrices (%s) returned %g-%g=%g", name, errf, eps, errf-eps);

  ambix_matrix_destroy(result);
  ambix_matrix_destroy(eye);
}
int test_defaultmatrix(const char*name, uint32_t rows, uint32_t cols, ambix_matrixtype_t mtyp,
		       uint32_t xtrachannels, uint32_t chunksize, float32_t eps) {
  int result=0;
  ambix_matrix_t*mtx=0;
  STARTTEST("%s\n", name);
  mtx=ambix_matrix_init(rows,cols,mtx);
  if(!mtx)return 1;
  ambix_matrix_fill(mtx, mtyp);
  result=check_create_b2e(FILENAME_FILE, AMBIX_SAMPLEFORMAT_PCM16,
			  mtx,xtrachannels,
			  chunksize, FLOAT32, eps);
  ambix_matrix_destroy(mtx);
  return result;
}
Exemple #13
0
static void ambix_write_matrix(t_ambix_write *x, t_symbol*s, int argc, t_atom*argv) {
  int rows, cols;
  float32_t*data=NULL;
  int count;
  if(x->x_matrix)
    ambix_matrix_destroy(x->x_matrix);
  x->x_matrix=NULL;
  if(argc>=2) {
    rows=atom_getint(argv+0);
    cols=atom_getint(argv+1);
    argc-=2;
    argv+=2;
  } else {
    pd_error(x, "invalid matrix message");
    return;
  }
  if(argc!=rows*cols) {
    pd_error(x, "invalid matrix");
    return;
  }
  data=(float32_t*)malloc(rows*cols*sizeof(float32_t));
  for(count=0; count<argc; count++) {
    data[count]=atom_getfloat(argv+count);
  }

  x->x_matrix=ambix_matrix_init(rows, cols, x->x_matrix);
  if(AMBIX_ERR_SUCCESS!=ambix_matrix_fill_data(x->x_matrix, data)) {
    pd_error(x, "invalid matrix data [%dx%d]=%p", rows, cols, data);
    if(x->x_matrix)
      ambix_matrix_destroy(x->x_matrix);
    x->x_matrix=NULL;
  }
  free(data);

  if(x->x_matrix)
    printmatrix(x->x_matrix);
}
Exemple #14
0
static ambix_matrix_t*matrix_read(const char*path, ambix_matrix_t*matrix) {
  SF_INFO info;
  uint32_t rows, cols;
  float*data=NULL;
  ambix_matrix_t*mtx=NULL, *result=NULL;
  uint32_t frames;

  memset(&info, 0, sizeof(info));
  SNDFILE*file=sf_open(path, SFM_READ, &info);

  if(!file) {
    fprintf(stderr, "ambix_interleave: matrix open failed '%s'\n", path);
    return NULL;
  }
  rows=info.channels;
  cols=info.frames;
  data=(float*)malloc(rows*cols*sizeof(float));
  frames=sf_readf_float(file, data, cols);
  if(cols!=frames) {
    fprintf(stderr, "ambix_interleave: matrix reading %d frames returned %d\n", frames, cols);
    goto cleanup;
  }

  mtx=ambix_matrix_init(cols, rows, NULL);
  if(mtx && (AMBIX_ERR_SUCCESS==ambix_matrix_fill_data(mtx, data))) {
    uint32_t r, c;
    matrix=ambix_matrix_init(rows, cols, matrix);

    for(r=0; r<rows; r++)
      for(c=0; c<cols; c++)
        matrix->data[r][c]=mtx->data[c][r];
  }

  result=matrix;

  //  fprintf(stderr, "ambix_interleave: matrices not yet supported\n");
  cleanup:
  if(mtx)
    ambix_matrix_destroy(mtx);

  sf_close(file);
  free(data);

  return result;
}
Exemple #15
0
ambix_err_t
ambix_matrix_fill_data_transposed(ambix_matrix_t*mtx, const float32_t*data, int byteswap) {
  ambix_err_t err=AMBIX_ERR_SUCCESS;
  ambix_matrix_t*xtm=ambix_matrix_init(mtx->cols, mtx->rows, NULL);

  if(!xtm)
    return AMBIX_ERR_UNKNOWN;

  if(byteswap)
    err=_ambix_matrix_fill_data_byteswapped(xtm, (const number32_t*)data);
  else
    err=ambix_matrix_fill_data(xtm, data);

  if(AMBIX_ERR_SUCCESS==err) {
    ambix_matrix_t*resu=ambix_matrix_transpose(mtx, xtm);
    if(!resu)
      err=AMBIX_ERR_UNKNOWN;
  }

  ambix_matrix_destroy(xtm);
  return err;
}
Exemple #16
0
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);
}
Exemple #17
0
int main(int argc, char *argv[])
{
  const char*filename = "jtest.caf";
  const char*myname=argv[0];
  observe_signals ();
  struct recorder d;

  ambix_matrix_t*matrix=NULL;
  int32_t order = -1;

  d.buffer_frames = 4096;
  d.minimal_frames = 32;
  d.channels = 2;
  d.timer_seconds = -1.0;
  d.timer_counter = 0;
  d.sample_format = AMBIX_SAMPLEFORMAT_FLOAT32;
  d.file_format   = AMBIX_BASIC;
  int c;
  while((c = getopt(argc, argv, "hVx:X:O:b:fhm:n:t:")) != -1) {
    switch(c) {
    case 'x':
      d.e_channels = (int) strtol(optarg, NULL, 0);
      d.file_format   = AMBIX_EXTENDED;
      break;
    case 'X':
      matrix=matrix_read(optarg, matrix);
      if(!matrix) {
        eprintf("%s: couldn't read matrix-file '%s'\n", myname, optarg);
        FAILURE;
      }
      d.file_format   = AMBIX_EXTENDED;
      break;
    case 'O':
      order = (uint32_t) strtol(optarg, NULL, 0);
      break;

    case 'b':
      d.buffer_frames = (int) strtol(optarg, NULL, 0);
      break;
#if 0
    case 'f':
      d.file_format = (int) strtol(optarg, NULL, 0);
      break;
#endif
    case 'V':
      version (myname);
      break;
    case 'h':
      usage (myname);
      break;
    case 'm':
      d.minimal_frames = (int) strtol(optarg, NULL, 0);
      break;
    case 't':
      d.timer_seconds = (float) strtod(optarg, NULL);
      break;
    default:
      eprintf("%s: illegal option, %c\n", myname, c);
      usage (myname);
      break;
    }
  }

  if(optind == argc - 1) {
    filename=argv[optind];
  } else {
    eprintf("opening default file '%s'\n", filename);
    //usage (myname);
  }

  /* Allocate channel based data. */
  if(matrix) {
    if(order<0) {
      d.a_channels = matrix->cols;
    } else {
      if(ambix_order2channels(order) != matrix->rows) {
        eprintf("%s: ambisonics order:%d cannot use [%dx%d] adaptor matrix.\n", myname, order, matrix->rows, matrix->cols);
        FAILURE;
      }
      d.a_channels = matrix->cols;
    }
  } else {
    if(order<0)
      order=1;

    d.a_channels=ambix_order2channels(order);
  }

  switch(d.file_format) {
  case AMBIX_BASIC:
    //d.a_channels;
    d.e_channels=0;
    break;
  case AMBIX_EXTENDED:
    //d.a_channels;
    //d.e_channels;
    break;
  case AMBIX_NONE: default:
    d.a_channels=0;
    //d.e_channels;
  }
  d.channels = d.a_channels+d.e_channels;


  if(d.channels < 1) {
    eprintf("%s: illegal number of channels: %d\n", myname, d.channels);
    FAILURE;
  }
  d.in = (float**)xmalloc(d.channels * sizeof(float *));
  d.input_port = (jack_port_t**)xmalloc(d.channels * sizeof(jack_port_t *));

  /* Connect to JACK. */
  
  jack_client_t *client = jack_client_unique_("ambix-jrecord");
  jack_set_error_function(jack_client_minimal_error_handler);
  jack_on_shutdown(client, jack_client_minimal_shutdown_handler, 0);
  jack_set_process_callback(client, process, &d);
  d.sample_rate = jack_get_sample_rate(client);

  /* Setup timer. */

  if(d.timer_seconds < 0.0) {
    d.timer_frames = -1;
  } else {
    d.timer_frames = d.timer_seconds * d.sample_rate;
  }

  /* Create sound file. */

  ambix_info_t sfinfo;
  memset(&sfinfo, 0, sizeof(sfinfo));
  sfinfo.samplerate = (int) d.sample_rate;
  sfinfo.frames = 0;
  sfinfo.fileformat = d.file_format;

  sfinfo.ambichannels  = d.a_channels;
  sfinfo.extrachannels = d.e_channels;

  d.sound_file = ambix_open(filename, AMBIX_WRITE, &sfinfo);

  if(matrix) {
    ambix_err_t aerr = ambix_set_adaptormatrix(d.sound_file, matrix);
    if(AMBIX_ERR_SUCCESS != aerr) {
      eprintf("setting [%dx%d] matrix returned %d.\n", matrix->rows, matrix->cols, aerr);
      FAILURE;
    }
  }

  /* Allocate buffers. */
  
  d.buffer_samples = d.buffer_frames * d.channels;
  d.buffer_bytes = d.buffer_samples * sizeof(float);

  d.a_buffer = (float32_t*)xmalloc(d.buffer_frames * d.a_channels * sizeof(float32_t));
  d.e_buffer = (float32_t*)xmalloc(d.buffer_frames * d.e_channels * sizeof(float32_t));

  d.d_buffer = (float*)xmalloc(d.buffer_bytes);
  d.j_buffer = (float*)xmalloc(d.buffer_bytes);
  d.u_buffer = (float*)xmalloc(d.buffer_bytes);
  d.ring_buffer = jack_ringbuffer_create(d.buffer_bytes);

  /* Create communication pipe. */

  xpipe(d.pipe);

  /* Start disk thread. */

  pthread_create (&(d.disk_thread),
		  NULL, 
		  disk_thread_procedure, 
		  &d);

  /* Create input ports and activate client. */

#if 0
  jack_port_make_standard(client, d.input_port, d.channels, false);
  jack_client_activate(client);
#else
  do {
    int i=0, a, e;
    const char*format=(sfinfo.fileformat == AMBIX_BASIC)?"ACN_%d":"ambisonics_%d";
    const int a_offset=(sfinfo.fileformat == AMBIX_BASIC)?0:1;
    for(a=0; a<d.a_channels; a++) {
      d.input_port[i] = _jack_port_register(client, JackPortIsInput, format, a+a_offset);
      i++;
    }
    for(e=0; e<d.e_channels; e++) {
      d.input_port[i] = _jack_port_register(client, JackPortIsInput, "in_%d", e+1);
      i++;
    }
  } while(0);

  if(jack_activate(client)) {
    eprintf("jack_activate() failed\n");
    FAILURE;
  }
#endif

  /* Wait for disk thread to end, which it does when it reaches the
     end of the file or is interrupted. */

  pthread_join(d.disk_thread, NULL);

  /* Close sound file, free ring buffer, close JACK connection, close
     pipe, free data buffers, indicate success. */

  jack_client_close(client);
  ambix_close(d.sound_file);
  jack_ringbuffer_free(d.ring_buffer);
  close(d.pipe[0]);
  close(d.pipe[1]);

  free(d.a_buffer);
  free(d.e_buffer);

  free(d.d_buffer);
  free(d.j_buffer);
  free(d.u_buffer);
  free(d.in);
  free(d.input_port);
  if(matrix)ambix_matrix_destroy(matrix);
  return EXIT_SUCCESS;
}
Exemple #18
0
void mtx_diff(float32_t eps) {
  float32_t errf;
  ambix_matrix_t *left=NULL, *right=NULL;
  unsigned int i;
  const unsigned int rows=4;
  const unsigned int cols=3;
  float32_t*leftdata=leftdata_4_3;
  float32_t*rightdata=malloc(sizeof(leftdata_4_3));
  float32_t maxeps=eps;

  STARTTEST("\n");

  left=ambix_matrix_create();
  right=ambix_matrix_create();

  /* comparisons:
     - failing tests:
       - different dimensions
       - left/right matrix is NULL
     - non-failing tests:
       - all values diff==0
       - all values diff<eps
       - few values diff<eps
       - many values diff<eps
  */
  fail_if((left !=ambix_matrix_init(3, 4, left )), __LINE__, "initializing left matrix failed");
  fail_if((right!=ambix_matrix_init(3, 4, right)), __LINE__, "initializing right matrix failed");

  /* compare equal matrices */
  STARTTEST("ident\n");
  ambix_matrix_fill_data(left, leftdata);
  errf=matrix_diff(__LINE__, left, left, eps);
  fail_if(errf>0.f, __LINE__, "diffing mtx with itself returned %g (>%g)", errf, 0.f);

  /* compare equal matrices */
  STARTTEST("equal\n");
  for(i=0; i<rows*cols; i++) {
    rightdata[i]=leftdata[i];
  }
  ambix_matrix_fill_data(left , leftdata);
  ambix_matrix_fill_data(right, rightdata);
  errf=matrix_diff(__LINE__, left, right, eps);
  fail_if(errf>0.f, __LINE__, "diffing mtx with copy returned %g (>%g)", errf, 0.f);

  /* compare matrices where all values differ, but <eps */
  STARTTEST("all<eps\n");
  for(i=0; i<rows*cols; i++) {
    rightdata[i]=leftdata[i]+eps*0.5;
  }
  ambix_matrix_fill_data(left , leftdata);
  ambix_matrix_fill_data(right, rightdata);
  errf=matrix_diff(__LINE__, left, right, eps);
  fail_if(errf>eps, __LINE__, "diffing mtx with mtx+eps/2 returned %g (>%g)", errf, eps);
  for(i=0; i<rows*cols; i++) {
    rightdata[i]=leftdata[i]-eps*0.5;
  }
  ambix_matrix_fill_data(left , leftdata);
  ambix_matrix_fill_data(right, rightdata);
  errf=matrix_diff(__LINE__, left, right, eps);
  fail_if(errf>eps, __LINE__, "diffing mtx with mtx-eps/2 returned %g (>%g)", errf, eps);

  /* compare matrices where many values differ with <eps; but one with >eps */
  STARTTEST("most<eps;one>eps\n");
  for(i=0; i<rows*cols; i++) {
    rightdata[i]=leftdata[i];
  }
  for(i=0; i<rows; i++) {
    rightdata[i]=leftdata[i]+eps*0.5;
  }
  rightdata[0]=leftdata[0]+eps*1.5;
  ambix_matrix_fill_data(left , leftdata);
  ambix_matrix_fill_data(right, rightdata);
  errf=matrix_diff(__LINE__, left, right, eps);
  fail_if(errf>(eps*2.0), __LINE__, "diffing mtx with one value>eps returned %g (>%g)", errf, eps);
  fail_if(errf<(eps*1.0), __LINE__, "diffing mtx with one value>eps returned %g (>%g)", errf, eps);

  /* compare matrices where most values differ with >eps */
  STARTTEST("most>eps\n");
  for(i=0; i<rows*cols; i++) {
    rightdata[i]=leftdata[i];
  }
  maxeps=eps*1.5;
  for(i=0; i<(rows*cols)-1; i++) {
    rightdata[i]=leftdata[i]-maxeps;
  }
  ambix_matrix_fill_data(left , leftdata);
  ambix_matrix_fill_data(right, rightdata);
  errf=matrix_diff(__LINE__, left, right, eps);
  fail_if(errf<eps*1.0, __LINE__, "diffing mtx with one value>eps returned %g (<%g)", errf, eps*1.0);
  fail_if(errf>eps*2.0, __LINE__, "diffing mtx with one value>eps returned %g (<%g)", errf, eps*2.0);

  ambix_matrix_destroy(left);
  ambix_matrix_destroy(right);
  free(rightdata);
  STOPTEST("\n");
}
Exemple #19
0
/* this modifies the input matrix! */
ambix_matrix_t*
_ambix_matrix_invert_gaussjordan(ambix_matrix_t*input, ambix_matrix_t*inverse, float32_t eps)
{
  ambix_matrix_t*inverse_org = inverse;
  int i, k;
  float32_t *a1, *b1, *a2, *b2;

  int errors=0; /* error counter */

  if(input==0)
    { // no input matrix
      return NULL;
    }

  if (input->cols != input->rows)
    {// matrix is not squared
      return NULL;
    }

  int col=input->cols, row=input->rows;

  /* 1a reserve space for the inverted matrix */
  if(!inverse)
    {
      inverse=ambix_matrix_init(row, col, NULL);
    }

  float32_t **original=input->data;
  float32_t **inverted=inverse->data;


  /* 1b make an eye-shaped float-buf for B */
  ambix_matrix_fill(inverse, AMBIX_MATRIX_IDENTITY);

  /* 2. do the Gauss-Jordan */
  //printf("GaussJordan\n");
  for (k=0; k<row; k++) {
    /* adjust current row */
    float32_t diagel = original[k][k];
    float32_t i_diagel = 0;
    if(diagel>-eps && diagel<eps)
      errors++;
    else
      i_diagel = 1./diagel;

    /* normalize current row (set the diagonal-element to 1 */
    for (i=0; i < row; i++)
      {
        original[k][i] *= i_diagel;
        inverted[k][i] *= i_diagel;
      }

    /* eliminate the k-th element in each row by adding the weighted normalized row */
    for (i=0; i < row; i++)
      {
        if (i-k)
          {
            float32_t f =-original[i][k];
            int j;
            for (j=row-1; j >= 0; j--) {
              original[i][j] += f * original[k][j];
              inverted[i][j] += f * inverted[k][j];
            }
          }
      }
  }

  if (errors > 0) {
    if(inverse != inverse_org)
      /* if the 'inverse' was locally allocated, free it */
      ambix_matrix_destroy(inverse);
    inverse=NULL;
  }

  return inverse;
}
Exemple #20
0
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;
}
Exemple #21
0
void mtxinverse_tests(float32_t eps) {
  float32_t errf;
  ambix_matrix_t *mtx=0, *testresult=0;
  float32_t*transposedata = (float32_t*)calloc(3*4, sizeof(float32_t));

  STARTTEST("\n");

  /* fill in some test data 4x4 */
  STARTTEST("[4x4]\n");
  mtx=ambix_matrix_init(4, 4, mtx);
  ambix_matrix_fill_data(mtx, leftdata_4_4);
  testresult=ambix_matrix_init(4, 4, testresult);
  ambix_matrix_fill_data(testresult, resultpinv_4_4);
  mtxinverse_test(mtx, testresult, eps);

  /* fill in some test data 4x3 */
  STARTTEST("[4x3]\n");
  mtx=ambix_matrix_init(4, 3, mtx);
  ambix_matrix_fill_data(mtx, leftdata_4_3);
  testresult=ambix_matrix_init(3, 4, testresult);
  ambix_matrix_fill_data(testresult, resultpinv_4_3);
  mtxinverse_test(mtx, testresult, eps);

  /* fill in some test data 3x4 */
  STARTTEST("[3x4]\n");
  data_transpose(transposedata, leftdata_4_3, 4, 3);
  mtx=ambix_matrix_init(3, 4, mtx);
  ambix_matrix_fill_data(mtx, transposedata);

  data_transpose(transposedata, resultpinv_4_3, 3, 4);
  testresult=ambix_matrix_init(4, 3, testresult);
  ambix_matrix_fill_data(testresult, transposedata);
  mtxinverse_test(mtx, testresult, eps);

  /* fill in some test data 4x4 */
  STARTTEST("[identity:4x4]\n");
  mtx=ambix_matrix_init(4, 4, mtx);
  ambix_matrix_fill(mtx, AMBIX_MATRIX_IDENTITY);
  testresult=ambix_matrix_init(4, 4, testresult);
  ambix_matrix_fill(testresult, AMBIX_MATRIX_IDENTITY);
  mtxinverse_test(mtx, testresult, eps);

  STARTTEST("[one:4x4]\n");
  mtx=ambix_matrix_init(4, 4, mtx);
  ambix_matrix_fill(mtx, AMBIX_MATRIX_ONE);
  mtxinverse_test(mtx, NULL, eps);
  STARTTEST("[zero:4x4]\n");
  mtx=ambix_matrix_init(4, 4, mtx);
  ambix_matrix_fill(mtx, AMBIX_MATRIX_ZERO);
  mtxinverse_test(mtx, NULL, eps);

  STARTTEST("[SID:4x4]\n");
  mtx=ambix_matrix_init(4, 4, mtx);
  ambix_matrix_fill(mtx, AMBIX_MATRIX_SID);
  testresult=ambix_matrix_init(4, 4, testresult);
  ambix_matrix_fill(testresult, AMBIX_MATRIX_TO_SID);
  mtxinverse_test(mtx, testresult, eps);

  STARTTEST("[N3D:4x4]\n");
  mtx=ambix_matrix_init(4, 4, mtx);
  ambix_matrix_fill(mtx, AMBIX_MATRIX_N3D);
  testresult=ambix_matrix_init(4, 4, testresult);
  ambix_matrix_fill(testresult, AMBIX_MATRIX_TO_N3D);
  mtxinverse_test(mtx, testresult, eps);

  STARTTEST("[FUMA:4x4]\n");
  mtx=ambix_matrix_init(4, 4, mtx);
  ambix_matrix_fill(mtx, AMBIX_MATRIX_FUMA);
  testresult=ambix_matrix_init(4, 4, testresult);
  ambix_matrix_fill(testresult, AMBIX_MATRIX_TO_FUMA);
  mtxinverse_test(mtx, testresult, eps);


  ambix_matrix_destroy(mtx);
  ambix_matrix_destroy(testresult);
  free(transposedata);
  STOPTEST("\n");
}