Esempio n. 1
0
int _matrix_sid2acn(float32_t*data, uint32_t count) {
  float32_t*datap=data;
  int32_t order=ambix_channels2order(count);
  int32_t o;
  if(order<0)return 0;

  for(o=0; o<=order; o++) {
    uint32_t offset=o>0?ambix_order2channels(o-1):0;
    int32_t maxindex=ambix_order2channels(o)-offset;

    int32_t index;

    for(index=1; index<maxindex; index+=2) {
      *datap++=(float32_t)(index+offset);
    }
    for(index=maxindex-1; index>=0; index-=2) {
      *datap++=(float32_t)(index+offset);
    }
  }
  return 1;
}
Esempio n. 2
0
ambix_err_t _ambix_open	(ambix_t*ambix, const char *path, const ambix_filemode_t mode, const ambix_info_t*ambixinfo) {
  int sfmode=0;
  int caf=0;

  ambix->private_data=calloc(1, sizeof(ambixsndfile_private_t));
  ambix2sndfile_info(ambixinfo, &PRIVATE(ambix)->sf_info);

  if((mode & AMBIX_READ) & (mode & AMBIX_WRITE))
    sfmode=	SFM_RDWR;
  else if (mode & AMBIX_WRITE)
    sfmode=	SFM_WRITE;
  else if (mode & AMBIX_READ)
    sfmode=	SFM_READ;

  PRIVATE(ambix)->sf_file=sf_open(path, sfmode, &PRIVATE(ambix)->sf_info) ;
  if(!PRIVATE(ambix)->sf_file)
    return AMBIX_ERR_INVALID_FILE;

  memset(&ambix->realinfo, 0, sizeof(*ambixinfo));
  sndfile2ambix_info(&PRIVATE(ambix)->sf_info, &ambix->realinfo);

  ambix->byteswap=(sf_command(PRIVATE(ambix)->sf_file, SFC_RAW_DATA_NEEDS_ENDSWAP, NULL, 0) == SF_TRUE);
  ambix->channels = PRIVATE(ambix)->sf_info.channels;

  caf=((SF_FORMAT_CAF == (SF_FORMAT_TYPEMASK & PRIVATE(ambix)->sf_info.format)) != 0);
  if(caf) {
    ambix->is_AMBIX=1;
    
    if(read_uuidchunk(ambix) == AMBIX_ERR_SUCCESS) {
      ambix->format=AMBIX_EXTENDED;
    } else {
      ambix->format=AMBIX_BASIC;
    }
  } else {
    // check whether this is an .amb file or the like...
    if(0) {
    } else if(sf_command(PRIVATE(ambix)->sf_file, SFC_WAVEX_GET_AMBISONIC, NULL, 0) == SF_AMBISONIC_B_FORMAT) {
      /*
        The four B-format signals are interleaved for each sample frame in the order W,X,Y,Z.

        If the extended six-channel B-Format is used, the U and V signals will occupy the
        fifth and sixth slots: W,X,Y,Z,U,V.

        If horizontal-only B-format  is to be represented, a three or five-channel file
        will suffice, with signals interleaved as W,X,Y (First Order), or W,X,Y,U,V (Second-order). 
        However, four and -six-channel files are also acceptable, with the Z channel empty. 
        Higher-order configurations are possible in theory, but are not addressed here. 
        A decoder program should either 'degrade gracefully', or reject formats it cannot handle.
        
        For all B-format configurations, the dwChannelMask field should be set to zero.

        Though strictly speaking an optional chunk, it is recommended that the PEAK chunk be
        used for all B-Format files. Apart from its general utility, it has the special virtue
        for B-format in that applications can determine from the peak value for the Z channel
        whether the file is indeed full periphonic B-format (with height information), or
        'Horizontal-only' (Z channel present but empty). 
      */
      switch(ambix->channels) {
      case  3: /* h   = 1st order 2-D */
        ambix_matrix_init(ambix_order2channels(1), ambix->channels, &ambix->matrix);
        break;
      case  4: /* f   = 1st order 3-D */
        ambix_matrix_init(ambix_order2channels(1), ambix->channels, &ambix->matrix);
        break;
      case  5: /* hh  = 2nd order 2-D */
        ambix_matrix_init(ambix_order2channels(2), ambix->channels, &ambix->matrix);
        break;
      case  6: /* fh  = 2nd order 2-D + 1st order 3-D (formerly called 2.5 order) */
        ambix_matrix_init(ambix_order2channels(2), ambix->channels, &ambix->matrix);
        break;
      case  7: /* hhh = 3rd order 2-D */
        ambix_matrix_init(ambix_order2channels(3), ambix->channels, &ambix->matrix);
        break;
      case  8: /* fhh = 3rd order 2-D + 1st order 3-D */
        ambix_matrix_init(ambix_order2channels(3), ambix->channels, &ambix->matrix);
        break;
      case  9: /* ff  = 2nd order 3-D */
        ambix_matrix_init(ambix_order2channels(2), ambix->channels, &ambix->matrix);
        break;
      case 11: /* ffh = 3rd order 2-D + 2nd order 3-D */
        ambix_matrix_init(ambix_order2channels(3), ambix->channels, &ambix->matrix);
        break;
      case 16: /* fff = 3rd order 3-D */
        ambix_matrix_init(ambix_order2channels(3), ambix->channels, &ambix->matrix);
        break;
      }
      if(NULL != ambix_matrix_fill(&ambix->matrix, AMBIX_MATRIX_FUMA)) {
        ambix->is_AMBIX=1;
        ambix->format=AMBIX_EXTENDED;
      } else {
        ambix->is_AMBIX=0;
        ambix->format=AMBIX_NONE;
      }
    } else {
      ambix->is_AMBIX=0;
      ambix->format=AMBIX_NONE;
    }
  }

  if(0) {
    print_sfinfo( &PRIVATE(ambix)->sf_info);
  }

  return AMBIX_ERR_SUCCESS;
}
Esempio n. 3
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;
}
Esempio n. 4
0
int main(int argc, char**argv) {
  uint32_t r, c, o;
  char name[64];
  name[63]=0;
  for(r=1; r<16; r++) {
    for(c=1; c<16; c++) {
      snprintf(name, 63, "zero[%d, %d]", r, c);
      check_matrix(name, AMBIX_MATRIX_ZERO, r, c);
      snprintf(name, 63, "one[%d, %d]", r, c);
      check_matrix(name, AMBIX_MATRIX_ONE, r, c);
      snprintf(name, 63, "identity[%d, %d]", r, c);
      check_matrix(name, AMBIX_MATRIX_IDENTITY, r, c);
    }
  }

  check_matrix("FuMa[ 1, 1]", AMBIX_MATRIX_FUMA,  1,  1);
  check_matrix("FuMa[ 4, 3]", AMBIX_MATRIX_FUMA,  4,  3);
  check_matrix("FuMa[ 4, 4]", AMBIX_MATRIX_FUMA,  4,  4);
  check_matrix("FuMa[ 9, 5]", AMBIX_MATRIX_FUMA,  9,  5);
  check_matrix("FuMa[ 9, 6]", AMBIX_MATRIX_FUMA,  9,  6);
  check_matrix("FuMa[ 9, 9]", AMBIX_MATRIX_FUMA,  9,  9);
  check_matrix("FuMa[16, 7]", AMBIX_MATRIX_FUMA, 16,  7);
  check_matrix("FuMa[16, 8]", AMBIX_MATRIX_FUMA, 16,  8);
  check_matrix("FuMa[16,11]", AMBIX_MATRIX_FUMA, 16, 11);
  check_matrix("FuMa[16,16]", AMBIX_MATRIX_FUMA, 16, 16);



  check_inversion("FuMa[ 1, 1]", AMBIX_MATRIX_FUMA,  1,  1);
  check_inversion("FuMa[ 4, 3]", AMBIX_MATRIX_FUMA,  4,  3);
  check_inversion("FuMa[ 4, 4]", AMBIX_MATRIX_FUMA,  4,  4);
  check_inversion("FuMa[ 9, 5]", AMBIX_MATRIX_FUMA,  9,  5);
  check_inversion("FuMa[ 9, 6]", AMBIX_MATRIX_FUMA,  9,  6);
  check_inversion("FuMa[ 9, 9]", AMBIX_MATRIX_FUMA,  9,  9);
  check_inversion("FuMa[16, 7]", AMBIX_MATRIX_FUMA, 16,  7);
  check_inversion("FuMa[16, 8]", AMBIX_MATRIX_FUMA, 16,  8);
  check_inversion("FuMa[16,11]", AMBIX_MATRIX_FUMA, 16, 11);
  check_inversion("FuMa[16,16]", AMBIX_MATRIX_FUMA, 16, 16);

  for(o=1; o<6; o++) {
    uint32_t chan=ambix_order2channels(o);
    snprintf(name, 63, "n3d2snd3d[%d, %d]", chan, chan);
    check_matrix(name, AMBIX_MATRIX_N3D, chan, chan);
    snprintf(name, 63, "sn3d2n3d[%d, %d]", chan, chan);
    check_matrix(name, AMBIX_MATRIX_TO_N3D, chan, chan);
    snprintf(name, 63, "n3d[%d, %d]", chan, chan);
    check_inversion(name, AMBIX_MATRIX_N3D,  1,  1);


    snprintf(name, 63, "sid2acn[%d, %d]", chan, chan);
    check_matrix(name, AMBIX_MATRIX_SID, chan, chan);
    snprintf(name, 63, "acn2sid[%d, %d]", chan, chan);
    check_matrix(name, AMBIX_MATRIX_TO_SID, chan, chan);

    snprintf(name, 63, "sid[%d, %d]", chan, chan);
    check_inversion(name, AMBIX_MATRIX_SID,  1,  1);
  }
    

  pass();
  return 0;
}