Changes in / [1c565c0:4cb2d54]


Ignore:
Location:
src
Files:
1 added
5 edited

Legend:

Unmodified
Added
Removed
  • src/io/sink.c

    r1c565c0 r4cb2d54  
    5454};
    5555
     56extern uint_t aubio_str_path_has_extension(const char_t *filename,
     57    const char_t *pattern);
     58
     59#ifdef HAVE_VORBISENC
     60typedef struct _aubio_sink_vorbis_t aubio_sink_vorbis_t;
     61extern aubio_sink_vorbis_t * new_aubio_sink_vorbis(const char_t *uri,
     62    uint_t samplerate);
     63extern void del_aubio_sink_vorbis (aubio_sink_vorbis_t *s);
     64extern uint_t aubio_sink_vorbis_open(aubio_sink_vorbis_t *s);
     65extern uint_t aubio_sink_vorbis_close(aubio_sink_vorbis_t *s);
     66extern uint_t aubio_sink_vorbis_preset_channels(aubio_sink_vorbis_t *s,
     67    uint_t channels);
     68extern uint_t aubio_sink_vorbis_preset_samplerate(aubio_sink_vorbis_t *s,
     69    uint_t samplerate);
     70extern uint_t aubio_sink_vorbis_get_channels(aubio_sink_vorbis_t *s);
     71extern uint_t aubio_sink_vorbis_get_samplerate(aubio_sink_vorbis_t *s);
     72extern void aubio_sink_vorbis_do(aubio_sink_vorbis_t *s, fvec_t*
     73    write_data, uint_t write);
     74extern void aubio_sink_vorbis_do_multi(aubio_sink_vorbis_t *s, fmat_t*
     75    write_data, uint_t write);
     76#endif /* HAVE_VORBISENC */
     77
     78#ifdef HAVE_FLAC
     79typedef struct _aubio_sink_flac_t aubio_sink_flac_t;
     80extern aubio_sink_flac_t * new_aubio_sink_flac(const char_t *uri,
     81    uint_t samplerate);
     82extern void del_aubio_sink_flac (aubio_sink_flac_t *s);
     83extern uint_t aubio_sink_flac_open(aubio_sink_flac_t *s);
     84extern uint_t aubio_sink_flac_close(aubio_sink_flac_t *s);
     85extern uint_t aubio_sink_flac_preset_channels(aubio_sink_flac_t *s,
     86    uint_t channels);
     87extern uint_t aubio_sink_flac_preset_samplerate(aubio_sink_flac_t *s,
     88    uint_t samplerate);
     89extern uint_t aubio_sink_flac_get_channels(aubio_sink_flac_t *s);
     90extern uint_t aubio_sink_flac_get_samplerate(aubio_sink_flac_t *s);
     91extern void aubio_sink_flac_do(aubio_sink_flac_t *s, fvec_t*
     92    write_data, uint_t write);
     93extern void aubio_sink_flac_do_multi(aubio_sink_flac_t *s, fmat_t*
     94    write_data, uint_t write);
     95#endif /* HAVE_FLAC */
     96
    5697aubio_sink_t * new_aubio_sink(const char_t * uri, uint_t samplerate) {
    5798  aubio_sink_t * s = AUBIO_NEW(aubio_sink_t);
     99
     100#ifdef HAVE_VORBISENC
     101  // check if this uri could be for us
     102  if (aubio_str_path_has_extension(uri, "ogg")) {
     103    s->sink = (void *)new_aubio_sink_vorbis(uri, samplerate);
     104    if (s->sink) {
     105      s->s_do = (aubio_sink_do_t)(aubio_sink_vorbis_do);
     106      s->s_do_multi = (aubio_sink_do_multi_t)(aubio_sink_vorbis_do_multi);
     107      s->s_preset_samplerate = (aubio_sink_preset_samplerate_t)(aubio_sink_vorbis_preset_samplerate);
     108      s->s_preset_channels = (aubio_sink_preset_channels_t)(aubio_sink_vorbis_preset_channels);
     109      s->s_get_samplerate = (aubio_sink_get_samplerate_t)(aubio_sink_vorbis_get_samplerate);
     110      s->s_get_channels = (aubio_sink_get_channels_t)(aubio_sink_vorbis_get_channels);
     111      s->s_close = (aubio_sink_close_t)(aubio_sink_vorbis_close);
     112      s->s_del = (del_aubio_sink_t)(del_aubio_sink_vorbis);
     113      return s;
     114    }
     115  }
     116#endif /* HAVE_VORBISENC */
     117
     118#ifdef HAVE_FLAC
     119  // check if this uri could be for us
     120  if (aubio_str_path_has_extension(uri, "flac")) {
     121    s->sink = (void *)new_aubio_sink_flac(uri, samplerate);
     122    if (s->sink) {
     123      s->s_do = (aubio_sink_do_t)(aubio_sink_flac_do);
     124      s->s_do_multi = (aubio_sink_do_multi_t)(aubio_sink_flac_do_multi);
     125      s->s_preset_samplerate = (aubio_sink_preset_samplerate_t)(aubio_sink_flac_preset_samplerate);
     126      s->s_preset_channels = (aubio_sink_preset_channels_t)(aubio_sink_flac_preset_channels);
     127      s->s_get_samplerate = (aubio_sink_get_samplerate_t)(aubio_sink_flac_get_samplerate);
     128      s->s_get_channels = (aubio_sink_get_channels_t)(aubio_sink_flac_get_channels);
     129      s->s_close = (aubio_sink_close_t)(aubio_sink_flac_close);
     130      s->s_del = (del_aubio_sink_t)(del_aubio_sink_flac);
     131      return s;
     132    }
     133  }
     134#endif /* HAVE_FLAC */
     135
    58136#ifdef HAVE_SINK_APPLE_AUDIO
    59137  s->sink = (void *)new_aubio_sink_apple_audio(uri, samplerate);
     
    100178#if !defined(HAVE_WAVWRITE) && \
    101179  !defined(HAVE_SNDFILE) && \
    102   !defined(HAVE_SINK_APPLE_AUDIO)
     180  !defined(HAVE_SINK_APPLE_AUDIO) && \
     181  !defined(HAVE_VORBISENC) && \
     182  !defined(HAVE_FLAC)
    103183  AUBIO_ERROR("sink: failed creating '%s' at %dHz (no sink built-in)\n", uri, samplerate);
    104184#endif
  • src/io/sink_apple_audio.c

    r1c565c0 r4cb2d54  
    3939uint_t aubio_sink_apple_audio_open(aubio_sink_apple_audio_t *s);
    4040
     41uint_t aubio_str_extension_matches(const char_t *ext,
     42    const char_t *pattern);
     43const char_t *aubio_str_get_extension(const char_t *filename);
     44
    4145#define MAX_SIZE 4096 // the maximum number of frames that can be written at a time
    4246
     
    5357  ExtAudioFileRef audioFile;
    5458  bool async;
     59  AudioFileTypeID fileType;
    5560};
    5661
     
    7176  s->channels = 0;
    7277
     78  aubio_sink_apple_audio_preset_format(s, aubio_str_get_extension(uri));
     79
    7380  // zero samplerate given. do not open yet
    7481  if ((sint_t)samplerate == 0) {
     
    121128}
    122129
     130uint_t aubio_sink_apple_audio_preset_format(aubio_sink_apple_audio_t *s,
     131    const char_t *fmt)
     132{
     133  if (aubio_str_extension_matches(fmt, "wav")) {
     134    s->fileType = kAudioFileWAVEType;
     135  } else if (aubio_str_extension_matches(fmt, "m4a")
     136      || aubio_str_extension_matches(fmt, "mp4") ) {
     137    // use alac for "mp4" and "m4a"
     138    s->fileType = kAudioFileM4AType;
     139  } else if (aubio_str_extension_matches(fmt, "aac") ) {
     140    // only use lossy codec for "aac"
     141    s->fileType = kAudioFileMPEG4Type;
     142  } else if (aubio_str_extension_matches(fmt, "aiff") ) {
     143    // only use lossy codec for "aac"
     144    s->fileType = kAudioFileAIFFType;
     145  } else {
     146    s->fileType = kAudioFileWAVEType;
     147    if (fmt && strnlen(fmt, PATH_MAX)) {
     148      AUBIO_WRN("sink_apple_audio: could not guess format for %s,"
     149         " using default (wav)\n", s->path);
     150      return AUBIO_FAIL;
     151    }
     152  }
     153  return AUBIO_OK;
     154}
     155
     156static void aubio_sink_apple_audio_set_client_format(aubio_sink_apple_audio_t* s,
     157    AudioStreamBasicDescription *clientFormat)
     158{
     159  memset(clientFormat, 0, sizeof(AudioStreamBasicDescription));
     160  // always set samplerate and channels first
     161  clientFormat->mSampleRate       = (Float64)(s->samplerate);
     162  clientFormat->mChannelsPerFrame = s->channels;
     163
     164  switch (s->fileType) {
     165    case kAudioFileM4AType:
     166      clientFormat->mFormatID         = kAudioFormatAppleLossless;
     167      break;
     168    case kAudioFileMPEG4Type:
     169      clientFormat->mFormatID         = kAudioFormatMPEG4AAC;
     170      clientFormat->mFormatFlags      = kMPEG4Object_AAC_Main;
     171      clientFormat->mFormatFlags     |= kAppleLosslessFormatFlag_16BitSourceData;
     172      clientFormat->mFramesPerPacket  = 1024;
     173      break;
     174    case kAudioFileWAVEType:
     175      clientFormat->mFormatID         = kAudioFormatLinearPCM;
     176      clientFormat->mFormatFlags      = kAudioFormatFlagIsSignedInteger;
     177      clientFormat->mFormatFlags     |= kAudioFormatFlagIsPacked;
     178      clientFormat->mBitsPerChannel   = sizeof(short) * 8;
     179      clientFormat->mFramesPerPacket  = 1;
     180      clientFormat->mBytesPerFrame    = clientFormat->mBitsPerChannel * clientFormat->mChannelsPerFrame / 8;
     181      clientFormat->mBytesPerPacket   = clientFormat->mFramesPerPacket * clientFormat->mBytesPerFrame;
     182      break;
     183    case kAudioFileAIFFType:
     184      clientFormat->mFormatID         = kAudioFormatLinearPCM;
     185      clientFormat->mFormatFlags      = kAudioFormatFlagIsSignedInteger;
     186      clientFormat->mFormatFlags     |= kAudioFormatFlagIsPacked;
     187      clientFormat->mFormatFlags     |= kAudioFormatFlagIsBigEndian;
     188      clientFormat->mBitsPerChannel   = sizeof(short) * 8;
     189      clientFormat->mFramesPerPacket  = 1;
     190      clientFormat->mBytesPerFrame    = clientFormat->mBitsPerChannel * clientFormat->mChannelsPerFrame / 8;
     191      clientFormat->mBytesPerPacket   = clientFormat->mFramesPerPacket * clientFormat->mBytesPerFrame;
     192      break;
     193    default:
     194      break;
     195  }
     196}
     197
    123198uint_t aubio_sink_apple_audio_get_samplerate(const aubio_sink_apple_audio_t *s)
    124199{
     
    135210  if (s->samplerate == 0 || s->channels == 0) return AUBIO_FAIL;
    136211
    137   AudioStreamBasicDescription clientFormat;
    138   memset(&clientFormat, 0, sizeof(AudioStreamBasicDescription));
    139   clientFormat.mFormatID         = kAudioFormatLinearPCM;
    140   clientFormat.mSampleRate       = (Float64)(s->samplerate);
    141   clientFormat.mFormatFlags      = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
    142   clientFormat.mChannelsPerFrame = s->channels;
    143   clientFormat.mBitsPerChannel   = sizeof(short) * 8;
    144   clientFormat.mFramesPerPacket  = 1;
    145   clientFormat.mBytesPerFrame    = clientFormat.mBitsPerChannel * clientFormat.mChannelsPerFrame / 8;
    146   clientFormat.mBytesPerPacket   = clientFormat.mFramesPerPacket * clientFormat.mBytesPerFrame;
    147   clientFormat.mReserved         = 0;
    148 
    149   AudioFileTypeID fileType = kAudioFileWAVEType;
    150212  CFURLRef fileURL = createURLFromPath(s->path);
    151213  bool overwrite = true;
     
    162224  inputFormat.mBytesPerFrame    = inputFormat.mBitsPerChannel * inputFormat.mChannelsPerFrame / 8;
    163225  inputFormat.mBytesPerPacket   = inputFormat.mFramesPerPacket * inputFormat.mBytesPerFrame;
     226
     227  // get the in-file format
     228  AudioStreamBasicDescription clientFormat;
     229  aubio_sink_apple_audio_set_client_format(s, &clientFormat);
     230
    164231  OSStatus err = noErr;
    165   err = ExtAudioFileCreateWithURL(fileURL, fileType, &clientFormat, NULL,
     232  err = ExtAudioFileCreateWithURL(fileURL, s->fileType, &clientFormat, NULL,
    166233     overwrite ? kAudioFileFlags_EraseFile : 0, &s->audioFile);
    167234  CFRelease(fileURL);
     
    173240    goto beach;
    174241  }
     242
     243#if defined(kAppleSoftwareAudioCodecManufacturer)
     244  // on iOS, set software based encoding before setting clientDataFormat
     245  UInt32 codecManf = kAppleSoftwareAudioCodecManufacturer;
     246  err = ExtAudioFileSetProperty(s->audioFile,
     247      kExtAudioFileProperty_CodecManufacturer,
     248      sizeof(UInt32), &codecManf);
     249  if (err) {
     250    char_t errorstr[20];
     251    AUBIO_ERR("sink_apple_audio: error when trying to set sofware codec on %s "
     252        "(%s)\n", s->path, getPrintableOSStatusError(errorstr, err));
     253    goto beach;
     254  }
     255#endif
    175256
    176257  err = ExtAudioFileSetProperty(s->audioFile,
  • src/io/sink_apple_audio.h

    r1c565c0 r4cb2d54  
    9797/**
    9898
     99  preset sink format
     100
     101  \param s sink, created with ::new_aubio_sink_apple_audio
     102  \param fmt format of the file to create
     103
     104  \return 0 on success, 1 on error
     105
     106  Preset the format of the sink. Supported format strings:
     107   - "wav": WAVE, 16 bit (default)
     108   - "aiff": AIFF, 16 bit
     109   - "m4a" or "mp4": Apple Audio Lossless Codec (ALAC)
     110   - "aac": Audio Advanced Codec, lossy
     111
     112  Full list of supported encoding format is available in Table 1-2 of
     113  `Multimedia Programming Guide
     114  <https://developer.apple.com/library/archive/documentation/AudioVideo/Conceptual/MultimediaPG/UsingAudio/UsingAudio.html>`_.
     115
     116 */
     117uint_t aubio_sink_apple_audio_preset_format(aubio_sink_apple_audio_t *s,
     118    const char_t *fmt);
     119
     120/**
     121
    99122  get samplerate of sink object
    100123
  • src/io/sink_sndfile.c

    r1c565c0 r4cb2d54  
    4949  uint_t scratch_size;
    5050  smpl_t *scratch_data;
     51  int format;
    5152};
    5253
    5354uint_t aubio_sink_sndfile_open(aubio_sink_sndfile_t *s);
     55
     56uint_t aubio_str_extension_matches(const char_t *ext,
     57    const char_t *pattern);
     58const char_t *aubio_str_get_extension(const char_t *filename);
    5459
    5560aubio_sink_sndfile_t * new_aubio_sink_sndfile(const char_t * path, uint_t samplerate) {
     
    6772  s->samplerate = 0;
    6873  s->channels = 0;
     74
     75  aubio_sink_sndfile_preset_format(s, aubio_str_get_extension(path));
    6976
    7077  // zero samplerate given. do not open yet
     
    112119  if (s->samplerate != 0 /* && s->channels != 0 */) {
    113120    return aubio_sink_sndfile_open(s);
     121  }
     122  return AUBIO_OK;
     123}
     124
     125uint_t aubio_sink_sndfile_preset_format(aubio_sink_sndfile_t *s,
     126    const char_t *fmt)
     127{
     128  if (aubio_str_extension_matches(fmt, "wav")) {
     129    s->format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
     130  } else if (aubio_str_extension_matches(fmt, "aiff")) {
     131    s->format = SF_FORMAT_AIFF | SF_FORMAT_PCM_16;
     132  } else if (aubio_str_extension_matches(fmt, "flac")) {
     133    s->format = SF_FORMAT_FLAC | SF_FORMAT_PCM_16;
     134  } else if (aubio_str_extension_matches(fmt, "ogg")) {
     135    s->format = SF_FORMAT_OGG | SF_FORMAT_VORBIS;
     136  } else if (atoi(fmt) > 0x010000) {
     137    s->format = atoi(fmt);
     138  } else {
     139    s->format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
     140    if (fmt && strnlen(fmt, PATH_MAX))  {
     141      AUBIO_WRN("sink_sndfile: could not guess format %s for %s,"
     142          " using default (wav)\n", fmt, s->path);
     143      return AUBIO_FAIL;
     144    }
    114145  }
    115146  return AUBIO_OK;
     
    132163  sfinfo.samplerate = s->samplerate;
    133164  sfinfo.channels   = s->channels;
    134   sfinfo.format     = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
     165  sfinfo.format     = s->format;
    135166
    136167  /* try creating the file */
  • src/io/sink_sndfile.h

    r1c565c0 r4cb2d54  
    9696/**
    9797
     98  preset sink format
     99
     100  \param s sink, created with ::new_aubio_sink_sndfile
     101  \param fmt format of the file to create
     102
     103  \return 0 on success, 1 on error
     104
     105  Preset the format of the sink. Supported format strings:
     106   - "wav": 16 bit (default)
     107   - "aiff": aiff, 16 bit
     108   - "flac": flac, 16 bit
     109   - "ogg": ogg vorbis stream
     110
     111  Alternatively, any sndfile format can be set by passing the corresponding
     112  integer as a string:
     113
     114  \code{.c}
     115  char_t fmt[10];
     116  snprintf(fmt, sizeof(fmt), "%d", SF_FORMAT_FLAC | SF_FORMAT_PCM_24);
     117  aubio_sink_sndfile_preset_format(s, fmt);
     118  \endcode
     119
     120  The file should have been created using a samplerate of 0.
     121
     122  This function should be called before aubio_sink_sndfile_preset_samplerate()
     123  and aubio_sink_sndfile_preset_channels().
     124
     125*/
     126uint_t aubio_sink_sndfile_preset_format(aubio_sink_sndfile_t *s,
     127        const char_t* fmt);
     128
     129/**
     130
    98131  get samplerate of sink object
    99132
Note: See TracChangeset for help on using the changeset viewer.