Changeset 870ad70


Ignore:
Timestamp:
Feb 23, 2014, 4:58:25 PM (6 years ago)
Author:
Paul Brossier <piem@piem.org>
Branches:
feature/autosink, feature/constantq, feature/pitchshift, feature/pydocstrings, feature/timestretch, master, pitchshift, sampler, timestretch, yinfft+
Children:
14ac1db
Parents:
222b176
Message:

src/io/sink_wavwrite.h: add do_multi, preset_samplerate, preset_channels, get_samplerate, and get_channels

Files:
1 added
2 edited

Legend:

Unmodified
Added
Removed
  • src/io/sink_wavwrite.c

    r222b176 r870ad70  
    2525
    2626#include "aubio_priv.h"
    27 #include "sink_wavwrite.h"
    2827#include "fvec.h"
     28#include "fmat.h"
     29#include "io/sink_wavwrite.h"
    2930
    3031#include <errno.h>
     
    4748#endif
    4849
     50uint_t aubio_sink_wavwrite_open(aubio_sink_wavwrite_t *s);
     51
    4952struct _aubio_sink_wavwrite_t {
    5053  char_t *path;
     
    7376aubio_sink_wavwrite_t * new_aubio_sink_wavwrite(char_t * path, uint_t samplerate) {
    7477  aubio_sink_wavwrite_t * s = AUBIO_NEW(aubio_sink_wavwrite_t);
    75   unsigned char buf[5];
    76   uint_t byterate, blockalign;
    7778
    7879  if (path == NULL) {
     
    8687
    8788  s->path = path;
    88   s->samplerate = samplerate;
    8989  s->max_size = MAX_SIZE;
    90   s->channels = 1;
    9190  s->bitspersample = 16;
    9291  s->total_frames_written = 0;
    9392
    94   /* set output format */
    95   s->fid = fopen((const char *)path, "wb");
    96   if (!s->fid) {
    97     AUBIO_ERR("sink_wavwrite: could not open %s (%s)\n", s->path, strerror(errno));
    98     goto beach;
    99   }
    100 
    101   // ChunkID
    102   fwrite("RIFF", 4, 1, s->fid);
    103 
    104   // ChunkSize (0 for now, actual size will be written in _close)
    105   fwrite(write_little_endian(0, buf, 4), 4, 1, s->fid);
    106 
    107   // Format
    108   fwrite("WAVE", 4, 1, s->fid);
    109 
    110   // Subchunk1ID
    111   fwrite("fmt ", 4, 1, s->fid);
    112 
    113   // Subchunk1Size
    114   fwrite(write_little_endian(16, buf, 4), 4, 1, s->fid);
    115 
    116   // AudioFormat
    117   fwrite(write_little_endian(1, buf, 2), 2, 1, s->fid);
    118 
    119   // NumChannels
    120   fwrite(write_little_endian(s->channels, buf, 2), 2, 1, s->fid);
    121 
    122   // SampleRate
    123   fwrite(write_little_endian(s->samplerate, buf, 4), 4, 1, s->fid);
    124 
    125   // ByteRate
    126   byterate = s->samplerate * s->channels * s->bitspersample / 8;
    127   fwrite(write_little_endian(byterate, buf, 4), 4, 1, s->fid);
    128 
    129   // BlockAlign
    130   blockalign = s->channels * s->bitspersample / 8;
    131   fwrite(write_little_endian(blockalign, buf, 2), 2, 1, s->fid);
    132 
    133   // BitsPerSample
    134   fwrite(write_little_endian(s->bitspersample, buf, 2), 2, 1, s->fid);
    135 
    136   // Subchunk2ID
    137   fwrite("data", 4, 1, s->fid);
    138 
    139   // Subchunk1Size (0 for now, actual size will be written in _close)
    140   fwrite(write_little_endian(0, buf, 4), 4, 1, s->fid);
    141 
    142   s->scratch_size = s->max_size * s->channels;
    143   /* allocate data for de/interleaving reallocated when needed. */
    144   if (s->scratch_size >= MAX_SIZE * MAX_CHANNELS) {
    145     AUBIO_ERR("sink_wavwrite: %d x %d exceeds maximum buffer size %d\n",
    146         s->max_size, s->channels, MAX_CHANNELS * MAX_CHANNELS);
    147     AUBIO_FREE(s);
    148     return NULL;
    149   }
    150   s->scratch_data = AUBIO_ARRAY(unsigned short,s->scratch_size);
     93  s->samplerate = 0;
     94  s->channels = 0;
     95
     96  // negative samplerate given, abort
     97  if ((sint_t)samplerate < 0) goto beach;
     98  // zero samplerate given. do not open yet
     99  if ((sint_t)samplerate == 0) return s;
     100
     101  s->samplerate = samplerate;
     102  s->channels = 1;
     103
     104  if (aubio_sink_wavwrite_open(s) != AUBIO_OK) {
     105    // open failed, abort
     106    goto beach;
     107  }
    151108
    152109  return s;
    153 
    154110beach:
    155111  //AUBIO_ERR("sink_wavwrite: failed creating %s with samplerate %dHz\n",
     
    159115}
    160116
     117uint_t aubio_sink_wavwrite_preset_samplerate(aubio_sink_wavwrite_t *s, uint_t samplerate)
     118{
     119  if ((sint_t)(samplerate) <= 0) return AUBIO_FAIL;
     120  s->samplerate = samplerate;
     121  // automatically open when both samplerate and channels have been set
     122  if (s->samplerate != 0 && s->channels != 0) {
     123    return aubio_sink_wavwrite_open(s);
     124  }
     125  return AUBIO_OK;
     126}
     127
     128uint_t aubio_sink_wavwrite_preset_channels(aubio_sink_wavwrite_t *s, uint_t channels)
     129{
     130  if ((sint_t)(channels) <= 0) return AUBIO_FAIL;
     131  s->channels = channels;
     132  // automatically open when both samplerate and channels have been set
     133  if (s->samplerate != 0 && s->channels != 0) {
     134    return aubio_sink_wavwrite_open(s);
     135  }
     136  return AUBIO_OK;
     137}
     138
     139uint_t aubio_sink_wavwrite_get_samplerate(aubio_sink_wavwrite_t *s)
     140{
     141  return s->samplerate;
     142}
     143
     144uint_t aubio_sink_wavwrite_get_channels(aubio_sink_wavwrite_t *s)
     145{
     146  return s->channels;
     147}
     148
     149uint_t aubio_sink_wavwrite_open(aubio_sink_wavwrite_t *s) {
     150  unsigned char buf[5];
     151  uint_t byterate, blockalign;
     152
     153  /* open output file */
     154  s->fid = fopen((const char *)s->path, "wb");
     155  if (!s->fid) {
     156    AUBIO_ERR("sink_wavwrite: could not open %s (%s)\n", s->path, strerror(errno));
     157    goto beach;
     158  }
     159
     160  // ChunkID
     161  fwrite("RIFF", 4, 1, s->fid);
     162
     163  // ChunkSize (0 for now, actual size will be written in _close)
     164  fwrite(write_little_endian(0, buf, 4), 4, 1, s->fid);
     165
     166  // Format
     167  fwrite("WAVE", 4, 1, s->fid);
     168
     169  // Subchunk1ID
     170  fwrite("fmt ", 4, 1, s->fid);
     171
     172  // Subchunk1Size
     173  fwrite(write_little_endian(16, buf, 4), 4, 1, s->fid);
     174
     175  // AudioFormat
     176  fwrite(write_little_endian(1, buf, 2), 2, 1, s->fid);
     177
     178  // NumChannels
     179  fwrite(write_little_endian(s->channels, buf, 2), 2, 1, s->fid);
     180
     181  // SampleRate
     182  fwrite(write_little_endian(s->samplerate, buf, 4), 4, 1, s->fid);
     183
     184  // ByteRate
     185  byterate = s->samplerate * s->channels * s->bitspersample / 8;
     186  fwrite(write_little_endian(byterate, buf, 4), 4, 1, s->fid);
     187
     188  // BlockAlign
     189  blockalign = s->channels * s->bitspersample / 8;
     190  fwrite(write_little_endian(blockalign, buf, 2), 2, 1, s->fid);
     191
     192  // BitsPerSample
     193  fwrite(write_little_endian(s->bitspersample, buf, 2), 2, 1, s->fid);
     194
     195  // Subchunk2ID
     196  fwrite("data", 4, 1, s->fid);
     197
     198  // Subchunk1Size (0 for now, actual size will be written in _close)
     199  fwrite(write_little_endian(0, buf, 4), 4, 1, s->fid);
     200
     201  s->scratch_size = s->max_size * s->channels;
     202  /* allocate data for de/interleaving reallocated when needed. */
     203  if (s->scratch_size >= MAX_SIZE * MAX_CHANNELS) {
     204    AUBIO_ERR("sink_wavwrite: %d x %d exceeds SIZE maximum buffer size %d\n",
     205        s->max_size, s->channels, MAX_SIZE * MAX_CHANNELS);
     206    goto beach;
     207  }
     208  s->scratch_data = AUBIO_ARRAY(unsigned short,s->scratch_size);
     209
     210  return AUBIO_OK;
     211
     212beach:
     213  return AUBIO_FAIL;
     214}
     215
    161216
    162217void aubio_sink_wavwrite_do(aubio_sink_wavwrite_t *s, fvec_t * write_data, uint_t write){
     
    177232    AUBIO_WRN("sink_wavwrite: trying to write %d frames to %s, "
    178233        "but only %d could be written\n", write, s->path, written_frames);
     234  }
     235  s->total_frames_written += written_frames;
     236  return;
     237}
     238
     239void aubio_sink_wavwrite_do_multi(aubio_sink_wavwrite_t *s, fmat_t * write_data, uint_t write){
     240  uint_t c = 0, i = 0, written_frames = 0;
     241
     242  if (write > s->max_size) {
     243    AUBIO_WRN("sink_wavwrite: trying to write %d frames to %s, "
     244        "but only %d can be written at a time\n", write, s->path, s->max_size);
     245    write = s->max_size;
     246  }
     247
     248  for (c = 0; c < s->channels; c++) {
     249    for (i = 0; i < write; i++) {
     250      s->scratch_data[i * s->channels + c] = HTOLES(FLOAT_TO_SHORT(write_data->data[c][i]));
     251    }
     252  }
     253  written_frames = fwrite(s->scratch_data, 2, write * s->channels, s->fid);
     254
     255  if (written_frames != write * s->channels) {
     256    AUBIO_WRN("sink_wavwrite: trying to write %d frames to %s, "
     257        "but only %d could be written\n", write, s->path, written_frames / s->channels);
    179258  }
    180259  s->total_frames_written += written_frames;
  • src/io/sink_wavwrite.h

    r222b176 r870ad70  
    2424/** \file
    2525
    26   Write to file using [libsndfile](http://www.mega-nerd.com/libsndfile/)
     26  Write to file using native file writer.
    2727
    2828  Avoid including this file directly! Prefer using ::aubio_sink_t instead to
     
    3939#endif
    4040
     41/** sink_wavwrite object */
    4142typedef struct _aubio_sink_wavwrite_t aubio_sink_wavwrite_t;
    4243
     
    5253  Creates a new sink object.
    5354
     55  If samplerate is set to 0, the creation of the file will be delayed until
     56  both ::aubio_sink_preset_samplerate and ::aubio_sink_preset_channels have
     57  been called.
     58
    5459*/
    5560aubio_sink_wavwrite_t * new_aubio_sink_wavwrite(char_t * uri, uint_t samplerate);
     61
     62/**
     63
     64  preset sink samplerate
     65
     66  \param s sink, created with ::new_aubio_sink_wavwrite
     67  \param samplerate samplerate to preset the sink to, in Hz
     68
     69  \return 0 on success, 1 on error
     70
     71  Preset the samplerate of the sink. The file should have been created using a
     72  samplerate of 0.
     73
     74  The file will be opened only when both samplerate and channels have been set.
     75
     76*/
     77uint_t aubio_sink_wavwrite_preset_samplerate(aubio_sink_wavwrite_t *s, uint_t samplerate);
     78
     79/**
     80
     81  preset sink channels
     82
     83  \param s sink, created with ::new_aubio_sink_wavwrite
     84  \param channels number of channels to preset the sink to
     85
     86  \return 0 on success, 1 on error
     87
     88  Preset the samplerate of the sink. The file should have been created using a
     89  samplerate of 0.
     90
     91  The file will be opened only when both samplerate and channels have been set.
     92
     93*/
     94uint_t aubio_sink_wavwrite_preset_channels(aubio_sink_wavwrite_t *s, uint_t channels);
     95
     96/**
     97
     98  get samplerate of sink object
     99
     100  \param s sink object, created with ::new_aubio_sink_wavwrite
     101  \return samplerate, in Hz
     102
     103*/
     104uint_t aubio_sink_wavwrite_get_samplerate(aubio_sink_wavwrite_t *s);
     105
     106/**
     107
     108  get channels of sink object
     109
     110  \param s sink object, created with ::new_aubio_sink_wavwrite
     111  \return number of channels
     112
     113*/
     114uint_t aubio_sink_wavwrite_get_channels(aubio_sink_wavwrite_t *s);
    56115
    57116/**
     
    65124*/
    66125void aubio_sink_wavwrite_do(aubio_sink_wavwrite_t * s, fvec_t * write_data, uint_t write);
     126
     127/**
     128
     129  write polyphonic vector of length hop_size to sink
     130
     131  \param s sink, created with ::new_aubio_sink_wavwrite
     132  \param write_data ::fmat_t samples to write to sink
     133  \param write number of frames to write
     134
     135*/
     136void aubio_sink_wavwrite_do_multi(aubio_sink_wavwrite_t * s, fmat_t * write_data, uint_t write);
    67137
    68138/**
Note: See TracChangeset for help on using the changeset viewer.