diff options
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | audio_read.c | 977 | ||||
| -rw-r--r-- | audio_read.h | 9 | ||||
| -rw-r--r-- | common.h | 12 | ||||
| -rw-r--r-- | options.h | 1 | ||||
| -rw-r--r-- | toolame.c | 66 | ||||
| -rw-r--r-- | toolame.h | 2 | 
7 files changed, 656 insertions, 413 deletions
| @@ -96,7 +96,7 @@ CC_SWITCHES = $(OPTIM) $(REQUIRED) $(ARCH) $(PG) $(TWEAKS) $(WARNINGS) $(NEW_02L  PGM = toolame -LIBS =  -lm -lzmq +LIBS =  -lm -lzmq -ljack -lpthread  #nick burch's OS/2 fix  gagravarr@SoftHome.net  UNAME = $(shell uname) diff --git a/audio_read.c b/audio_read.c index afc4ad6..f5a4816 100644 --- a/audio_read.c +++ b/audio_read.c @@ -5,154 +5,349 @@  #include "encoder.h"  #include "options.h"  #include "portableio.h" +#include <pthread.h> +#include <jack/jack.h> +#include <jack/ringbuffer.h>  #include "audio_read.h" +jack_port_t *input_port_left; +jack_port_t *input_port_right; +jack_client_t *client; +pthread_mutex_t encode_thread_lock = PTHREAD_MUTEX_INITIALIZER; +pthread_cond_t  data_ready = PTHREAD_COND_INITIALIZER; + +/* shutdown can tell get_audio to stop */ +typedef struct _thread_info { +    volatile int connected; +} jack_thread_info_t; + +jack_thread_info_t thread_info; +const size_t sample_size = sizeof(jack_default_audio_sample_t); + +#define DEFAULT_RB_SIZE 16384       /* ringbuffer size in frames */ +jack_ringbuffer_t *rb; + +/* setup_jack() + * + * PURPOSE:  connect to jack, setup the ports, the ringbuffer + * + * frame_header is needed (fill information about sampling rate) + */ + +void setup_jack(frame_header *header, const char* jackname) { +    const char *client_name = jackname; +    const char *server_name = NULL; +    jack_options_t options = JackNullOption; +    jack_status_t status; + +    /* open a client connection to the JACK server */ + +    client = jack_client_open(client_name, options, &status, server_name); +    if (client == NULL) { +        fprintf(stderr, "jack_client_open() failed, " +                "status = 0x%2.0x\n", status); +        if (status & JackServerFailed) { +            fprintf(stderr, "Unable to connect to JACK server\n"); +        } +        exit(1); +    } +    if (status & JackServerStarted) { +        fprintf(stderr, "JACK server started\n"); +    } +    if (status & JackNameNotUnique) { +        client_name = jack_get_client_name(client); +        fprintf(stderr, "unique name `%s' assigned\n", client_name); +    } + +    thread_info.connected = 1; + +    /* tell the JACK server to call `process()' whenever +       there is work to be done. +       */ + +    jack_set_process_callback(client, process, &thread_info); + +    /* tell the JACK server to call `jack_shutdown()' if +       it ever shuts down, either entirely, or if it +       just decides to stop calling us. +       */ + +    jack_on_shutdown(client, jack_shutdown, &thread_info); + +    /* display the current sample rate.  +    */ + +    printf ("engine sample rate: %" PRIu32 "\n", +            jack_get_sample_rate(client)); + +    if ((header->sampling_frequency = SmpFrqIndex((long) jack_get_sample_rate(client), &header->version)) < 0) { +        fprintf (stderr, "invalid sample rate\n"); +        exit(1); +    } + +    /* create two ports */ + +    input_port_left = jack_port_register(client, "in_left", +            JACK_DEFAULT_AUDIO_TYPE, +            JackPortIsInput, 0); +    input_port_right = jack_port_register(client, "in_right", +            JACK_DEFAULT_AUDIO_TYPE, +            JackPortIsInput, 0); + +    if ((input_port_left == NULL) || (input_port_right == NULL)) { +        fprintf(stderr, "no more JACK ports available\n"); +        exit(1); +    } + + +    /* setup the ringbuffer */ +    rb = jack_ringbuffer_create(2 * sample_size * DEFAULT_RB_SIZE); +    fprintf(stderr, "jack sample_size: %zu\n", sample_size); + + +    /* take the mutex */ +    pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); +    pthread_mutex_lock(&encode_thread_lock); + +    /* Tell the JACK server that we are ready to roll.  Our +     * process() callback will start running now. */ + +    if (jack_activate(client)) { +        fprintf (stderr, "cannot activate client"); +        exit(1); +    } +} + +/** + * The process callback for this JACK application is called in a + * special realtime thread once for each audio cycle. + * + * It fills the ringbuffer + */ +int process(jack_nframes_t nframes, void *arg) { +    int i; +    int samp; +    //jack_thread_info_t *info = (jack_thread_info_t *) arg; + +    jack_default_audio_sample_t *in_left, *in_right; +    in_left = jack_port_get_buffer(input_port_left, nframes); +    in_right = jack_port_get_buffer(input_port_right, nframes); + +    /* Sndfile requires interleaved data.  It is simpler here to +     * just queue interleaved samples to a single ringbuffer. */ +    //fprintf(stderr, "process()\n"); +    for (i = 0; i < nframes; i++) { +        /* +           jack_ringbuffer_write(rb, (void *)(in_left + i), sample_size); +           jack_ringbuffer_write(rb, (void *)(in_right + i), sample_size); +        */ +        /* convert to shorts, then insert into ringbuffer */ +        samp = lrintf(in_left[i] * 1.0 * 0x7FFF); +        jack_ringbuffer_write(rb, (char*)&samp, 2);  +        samp = lrintf(in_right[i] * 1.0 * 0x7FFF); +        jack_ringbuffer_write(rb, (char*)&samp, 2);  +         +    } +    //fprintf(stderr, "PROCESS()\n"); + +    /* tell read_samples that we've got new data */ +    pthread_cond_signal(&data_ready); + +    return 0; +} + +/** + * JACK calls this shutdown_callback if the server ever shuts down or + * decides to disconnect the client. + */ +void jack_shutdown(void *arg) +{ +    jack_thread_info_t *info = (jack_thread_info_t *) arg; + +    info->connected = 0; +    /* tell read_samples to move on */ + +    pthread_cond_signal(&data_ready); +}  /************************************************************************ -* -* read_samples() -* -* PURPOSE:  reads the PCM samples from a file to the buffer -* -*  SEMANTICS: -* Reads #samples_read# number of shorts from #musicin# filepointer -* into #sample_buffer[]#.  Returns the number of samples read. -* -************************************************************************/ - -unsigned long -read_samples (FILE * musicin, short sample_buffer[2304], -              unsigned long num_samples, unsigned long frame_size) + * + * read_samples() + * + * PURPOSE:  reads the PCM samples from a file to the buffer + * + *  SEMANTICS: + * Reads #samples_read# number of shorts from #musicin# filepointer + * into #sample_buffer[]#.  Returns the number of samples read. + * + ************************************************************************/ + +unsigned long read_samples (music_in_t* musicin, short sample_buffer[2304], +        unsigned long num_samples, unsigned long frame_size)  { -  unsigned long samples_read; -  static unsigned long samples_to_read; -  static char init = TRUE; - -  if (init) { -    samples_to_read = num_samples; -    init = FALSE; -  } -  if (samples_to_read >= frame_size) -    samples_read = frame_size; -  else -    samples_read = samples_to_read; -  if ((samples_read = -       fread (sample_buffer, sizeof (short), (int) samples_read, -              musicin)) == 0) -    fprintf (stderr, "Hit end of audio data\n"); -  /* -     Samples are big-endian. If this is a little-endian machine -     we must swap -   */ -  if (NativeByteOrder == order_unknown) { -    NativeByteOrder = DetermineByteOrder (); +    unsigned long samples_read; +    static unsigned long samples_to_read; +    static char init = TRUE; + +    void* jack_sample_buffer; + +    if (init) { +        samples_to_read = num_samples; +        init = FALSE; +    } +    if (samples_to_read >= frame_size) +        samples_read = frame_size; +    else +        samples_read = samples_to_read; + +    if (glopts.enable_jack) { +        int f = 2; +        while (jack_ringbuffer_read_space(rb) < f * samples_read) { +            /* wait until process() signals more data */ +            pthread_cond_wait(&data_ready, &encode_thread_lock); + +            if (thread_info.connected == 0) { +                pthread_mutex_unlock(&encode_thread_lock); +                jack_client_close(client); +                jack_ringbuffer_free(rb); +                return 0; +            } +        } + +        jack_sample_buffer = malloc(f * (int)samples_read); +        int bytes_read = jack_ringbuffer_read(rb, jack_sample_buffer, f * (int)samples_read); +        //fprintf(stderr, " read_bytes / f = %d, should be %d\n", (int)bytes_read/f, samples_read); +        samples_read = bytes_read / f; +        if (bytes_read % f != 0) { +            fprintf(stderr, "cannot divide bytes_read by f: %d mod f = %d", bytes_read, bytes_read % f); +        } +        //fprintf(stderr, " #%d(%d) \n", (int)bytes_read, samples_read); +        //f2les_array(jack_sample_buffer, sample_buffer, samples_read, 1); + +        memcpy(sample_buffer, jack_sample_buffer, bytes_read); + +        free(jack_sample_buffer); + +    } +    else { +        if ((samples_read = +                    fread (sample_buffer, sizeof (short), (int) samples_read, +                        musicin->wav_input)) == 0) +            fprintf (stderr, "Hit end of audio data\n"); +    } +    /* +       Samples are big-endian. If this is a little-endian machine +       we must swap +       */      if (NativeByteOrder == order_unknown) { -      fprintf (stderr, "byte order not determined\n"); -      exit (1); +        NativeByteOrder = DetermineByteOrder (); +        if (NativeByteOrder == order_unknown) { +            fprintf (stderr, "byte order not determined\n"); +            exit (1); +        }      } -  } -  if (NativeByteOrder != order_littleEndian || (glopts.byteswap == TRUE)) -    SwapBytesInWords (sample_buffer, samples_read); - -  if (num_samples != MAX_U_32_NUM) -    samples_to_read -= samples_read; - -  if (samples_read < frame_size && samples_read > 0) { -    /* fill out frame with zeros */ -    for (; samples_read < frame_size; sample_buffer[samples_read++] = 0); -    samples_to_read = 0; -    samples_read = frame_size; -  } -  return (samples_read); +    if (NativeByteOrder != order_littleEndian || (glopts.byteswap == TRUE)) +        SwapBytesInWords (sample_buffer, samples_read); + +    if (num_samples != MAX_U_32_NUM) +        samples_to_read -= samples_read; + +    if (samples_read < frame_size && samples_read > 0) { +        /* fill out frame with zeros */ +        for (; samples_read < frame_size; sample_buffer[samples_read++] = 0); +        samples_to_read = 0; +        samples_read = frame_size; +    } +    return (samples_read);  }  /************************************************************************ -* -* get_audio() -* -* PURPOSE:  reads a frame of audio data from a file to the buffer, -*   aligns the data for future processing, and separates the -*   left and right channels -* -* -************************************************************************/ -unsigned long -get_audio (FILE * musicin, short buffer[2][1152], unsigned long num_samples, -           int nch, frame_header *header) + * + * get_audio() + * + * PURPOSE:  reads a frame of audio data from a file to the buffer, + *   aligns the data for future processing, and separates the + *   left and right channels + * + * + ************************************************************************/ +    unsigned long +get_audio (music_in_t* musicin, short buffer[2][1152], unsigned long num_samples, +        int nch, frame_header *header)  { -  int j; -  short insamp[2304]; -  unsigned long samples_read; - -  if (nch == 2) {               /* stereo */ -    samples_read = -      read_samples (musicin, insamp, num_samples, (unsigned long) 2304); -    if (glopts.channelswap == TRUE) { -      for (j = 0; j < 1152; j++) { -        buffer[1][j] = insamp[2 * j]; -        buffer[0][j] = insamp[2 * j + 1]; -      } -    } else { -      for (j = 0; j < 1152; j++) { -        buffer[0][j] = insamp[2 * j]; -        buffer[1][j] = insamp[2 * j + 1]; -      } -    } -  } else if (glopts.downmix == TRUE) { -    samples_read = -      read_samples (musicin, insamp, num_samples, (unsigned long) 2304); -    for (j = 0; j < 1152; j++) { -      buffer[0][j] = 0.5 * (insamp[2 * j] + insamp[2 * j + 1]); -    } -  } else {                      /* mono */ -    samples_read = -      read_samples (musicin, insamp, num_samples, (unsigned long) 1152); -    for (j = 0; j < 1152; j++) { -      buffer[0][j] = insamp[j]; -      /* buffer[1][j] = 0;  don't bother zeroing this buffer. MFC Nov 99 */ +    int j; +    short insamp[2304]; +    unsigned long samples_read; + +    if (nch == 2) {     /* stereo */ +        samples_read = +            read_samples (musicin, insamp, num_samples, (unsigned long) 2304); +        if (glopts.channelswap == TRUE) { +            for (j = 0; j < 1152; j++) { +                buffer[1][j] = insamp[2 * j]; +                buffer[0][j] = insamp[2 * j + 1]; +            } +        } else { +            for (j = 0; j < 1152; j++) { +                buffer[0][j] = insamp[2 * j]; +                buffer[1][j] = insamp[2 * j + 1]; +            } +        } +    } else if (glopts.downmix == TRUE) { +        samples_read = +            read_samples (musicin, insamp, num_samples, (unsigned long) 2304); +        for (j = 0; j < 1152; j++) { +            buffer[0][j] = 0.5 * (insamp[2 * j] + insamp[2 * j + 1]); +        } +    } else {            /* mono */ +        samples_read = +            read_samples (musicin, insamp, num_samples, (unsigned long) 1152); +        for (j = 0; j < 1152; j++) { +            buffer[0][j] = insamp[j]; +            /* buffer[1][j] = 0;  don't bother zeroing this buffer. MFC Nov 99 */ +        }      } -  } -  return (samples_read); +    return (samples_read);  }  /***************************************************************************** -* -*  Routines to determine byte order and swap bytes -* -*****************************************************************************/ + * + *  Routines to determine byte order and swap bytes + * + *****************************************************************************/  enum byte_order DetermineByteOrder (void)  { -  char s[sizeof (long) + 1]; -  union { -    long longval; -    char charval[sizeof (long)]; -  } probe; -  probe.longval = 0x41424344L;  /* ABCD in ASCII */ -  strncpy (s, probe.charval, sizeof (long)); -  s[sizeof (long)] = '\0'; -  /* fprintf( stderr, "byte order is %s\n", s ); */ -  if (strcmp (s, "ABCD") == 0) -    return order_bigEndian; -  else if (strcmp (s, "DCBA") == 0) -    return order_littleEndian; -  else -    return order_unknown; +    char s[sizeof (long) + 1]; +    union { +        long longval; +        char charval[sizeof (long)]; +    } probe; +    probe.longval = 0x41424344L;  /* ABCD in ASCII */ +    strncpy (s, probe.charval, sizeof (long)); +    s[sizeof (long)] = '\0'; +    /* fprintf( stderr, "byte order is %s\n", s ); */ +    if (strcmp (s, "ABCD") == 0) +        return order_bigEndian; +    else if (strcmp (s, "DCBA") == 0) +        return order_littleEndian; +    else +        return order_unknown;  }  void SwapBytesInWords (short *loc, int words)  { -  int i; -  short thisval; -  char *dst, *src; -  src = (char *) &thisval; -  for (i = 0; i < words; i++) { -    thisval = *loc; -    dst = (char *) loc++; -    dst[0] = src[1]; -    dst[1] = src[0]; -  } +    int i; +    short thisval; +    char *dst, *src; +    src = (char *) &thisval; +    for (i = 0; i < words; i++) { +        thisval = *loc; +        dst = (char *) loc++; +        dst[0] = src[1]; +        dst[1] = src[0]; +    }  }  /***************************************************************************** @@ -163,62 +358,62 @@ void SwapBytesInWords (short *loc, int words)  int aiff_read_headers (FILE * file_ptr, IFF_AIFF * aiff_ptr)  { -  int chunkSize, subSize, sound_position; - -  if (fseek (file_ptr, 0, SEEK_SET) != 0) -    return -1; - -  if (Read32BitsHighLow (file_ptr) != IFF_ID_FORM) -    return -1; - -  chunkSize = Read32BitsHighLow (file_ptr); - -  if (Read32BitsHighLow (file_ptr) != IFF_ID_AIFF) -    return -1; - -  sound_position = 0; -  while (chunkSize > 0) { -    chunkSize -= 4; -    switch (Read32BitsHighLow (file_ptr)) { - -    case IFF_ID_COMM: -      chunkSize -= subSize = Read32BitsHighLow (file_ptr); -      aiff_ptr->numChannels = Read16BitsHighLow (file_ptr); -      subSize -= 2; -      aiff_ptr->numSampleFrames = Read32BitsHighLow (file_ptr); -      subSize -= 4; -      aiff_ptr->sampleSize = Read16BitsHighLow (file_ptr); -      subSize -= 2; -      aiff_ptr->sampleRate = ReadIeeeExtendedHighLow (file_ptr); -      subSize -= 10; -      while (subSize > 0) { -        getc (file_ptr); -        subSize -= 1; -      } -      break; - -    case IFF_ID_SSND: -      chunkSize -= subSize = Read32BitsHighLow (file_ptr); -      aiff_ptr->blkAlgn.offset = Read32BitsHighLow (file_ptr); -      subSize -= 4; -      aiff_ptr->blkAlgn.blockSize = Read32BitsHighLow (file_ptr); -      subSize -= 4; -      sound_position = ftell (file_ptr) + aiff_ptr->blkAlgn.offset; -      if (fseek (file_ptr, (long) subSize, SEEK_CUR) != 0) +    int chunkSize, subSize, sound_position; + +    if (fseek (file_ptr, 0, SEEK_SET) != 0) +        return -1; + +    if (Read32BitsHighLow (file_ptr) != IFF_ID_FORM)          return -1; -      aiff_ptr->sampleType = IFF_ID_SSND; -      break; - -    default: -      chunkSize -= subSize = Read32BitsHighLow (file_ptr); -      while (subSize > 0) { -        getc (file_ptr); -        subSize -= 1; -      } -      break; + +    chunkSize = Read32BitsHighLow (file_ptr); + +    if (Read32BitsHighLow (file_ptr) != IFF_ID_AIFF) +        return -1; + +    sound_position = 0; +    while (chunkSize > 0) { +        chunkSize -= 4; +        switch (Read32BitsHighLow (file_ptr)) { + +            case IFF_ID_COMM: +                chunkSize -= subSize = Read32BitsHighLow (file_ptr); +                aiff_ptr->numChannels = Read16BitsHighLow (file_ptr); +                subSize -= 2; +                aiff_ptr->numSampleFrames = Read32BitsHighLow (file_ptr); +                subSize -= 4; +                aiff_ptr->sampleSize = Read16BitsHighLow (file_ptr); +                subSize -= 2; +                aiff_ptr->sampleRate = ReadIeeeExtendedHighLow (file_ptr); +                subSize -= 10; +                while (subSize > 0) { +                    getc (file_ptr); +                    subSize -= 1; +                } +                break; + +            case IFF_ID_SSND: +                chunkSize -= subSize = Read32BitsHighLow (file_ptr); +                aiff_ptr->blkAlgn.offset = Read32BitsHighLow (file_ptr); +                subSize -= 4; +                aiff_ptr->blkAlgn.blockSize = Read32BitsHighLow (file_ptr); +                subSize -= 4; +                sound_position = ftell (file_ptr) + aiff_ptr->blkAlgn.offset; +                if (fseek (file_ptr, (long) subSize, SEEK_CUR) != 0) +                    return -1; +                aiff_ptr->sampleType = IFF_ID_SSND; +                break; + +            default: +                chunkSize -= subSize = Read32BitsHighLow (file_ptr); +                while (subSize > 0) { +                    getc (file_ptr); +                    subSize -= 1; +                } +                break; +        }      } -  } -  return sound_position; +    return sound_position;  }  /***************************************************************************** @@ -229,236 +424,236 @@ int aiff_read_headers (FILE * file_ptr, IFF_AIFF * aiff_ptr)  int aiff_seek_to_sound_data (FILE * file_ptr)  { -  if (fseek -      (file_ptr, AIFF_FORM_HEADER_SIZE + AIFF_SSND_HEADER_SIZE, -       SEEK_SET) != 0) -    return (-1); -  return (0); +    if (fseek +            (file_ptr, AIFF_FORM_HEADER_SIZE + AIFF_SSND_HEADER_SIZE, +             SEEK_SET) != 0) +        return (-1); +    return (0);  }  /************************************************************ -*   parse_input_file() -*   Determine the type of sound file. (stdin, wav, aiff, raw pcm) -*   Determine Sampling Frequency -*             number of samples -*             whether the new sample is stereo or mono.  -* -*   If file is coming from /dev/stdin assume it is raw PCM. (it's what I use. YMMV) -* -*  This is just a hacked together function. The aiff parsing comes from the ISO code. -*  The WAV code comes from Nick Burch -*  The ugly /dev/stdin hack comes from me. -*                                                  MFC Dec 99 -**************************************************************/ -void + *   parse_input_file() + *   Determine the type of sound file. (stdin, wav, aiff, raw pcm) + *   Determine Sampling Frequency + *             number of samples + *             whether the new sample is stereo or mono.  + * + *   If file is coming from /dev/stdin assume it is raw PCM. (it's what I use. YMMV) + * + *  This is just a hacked together function. The aiff parsing comes from the ISO code. + *  The WAV code comes from Nick Burch + *  The ugly /dev/stdin hack comes from me. + *                                                  MFC Dec 99 + **************************************************************/ +    void  parse_input_file (FILE * musicin, char inPath[MAX_NAME_SIZE], frame_header *header, -                  unsigned long *num_samples) +        unsigned long *num_samples)  { -  IFF_AIFF pcm_aiff_data; -  long soundPosition; - -  unsigned char wave_header_buffer[40]; //HH fixed -  int wave_header_read = 0; -  int wave_header_stereo = -1; -  int wave_header_16bit = -1; -  unsigned long samplerate; - -  /*************************** STDIN ********************************/ -  /* check if we're reading from stdin. Assume it's a raw PCM file. */ -  /* Of course, you could be piping a WAV file into stdin. Not done in this code */ -  /* this code is probably very dodgy and was written to suit my needs. MFC Dec 99 */ -  if ((strcmp (inPath, "/dev/stdin") == 0)) { -    fprintf (stderr, "Reading from stdin\n"); -    fprintf (stderr, "Remember to set samplerate with '-s'.\n"); -    *num_samples = MAX_U_32_NUM;        /* huge sound file */ -    return; -  } - -  /****************************  AIFF ********************************/ -  if ((soundPosition = aiff_read_headers (musicin, &pcm_aiff_data)) != -1) { -    fprintf (stderr, ">>> Using Audio IFF sound file headers\n"); -    aiff_check (inPath, &pcm_aiff_data, &header->version); -    if (fseek (musicin, soundPosition, SEEK_SET) != 0) { -      fprintf (stderr, "Could not seek to PCM sound data in \"%s\".\n", -               inPath); -      exit (1); -    } -    fprintf (stderr, "Parsing AIFF audio file \n"); -    header->sampling_frequency = -      SmpFrqIndex ((long) pcm_aiff_data.sampleRate, &header->version); -    fprintf (stderr, ">>> %f Hz sampling frequency selected\n", -             pcm_aiff_data.sampleRate); - -    /* Determine number of samples in sound file */ -    *num_samples = pcm_aiff_data.numChannels * pcm_aiff_data.numSampleFrames; - -    if (pcm_aiff_data.numChannels == 1) { -      header->mode = MPG_MD_MONO; -      header->mode_ext = 0; -    } -    return; -  } - -  /**************************** WAVE *********************************/ -  /*   Nick Burch <The_Leveller@newmail.net> */ -  /*********************************/ -  /* Wave File Headers:   (Dec)    */ -  /* 8-11 = "WAVE"                 */ -  /* 22 = Stereo / Mono            */ -  /*       01 = mono, 02 = stereo  */ -  /* 24 = Sampling Frequency       */ -  /* 32 = Data Rate                */ -  /*       01 = x1 (8bit Mono)     */ -  /*       02 = x2 (8bit Stereo or */ -  /*                16bit Mono)    */ -  /*       04 = x4 (16bit Stereo)  */ -  /*********************************/ - -  fseek (musicin, 0, SEEK_SET); -  fread (wave_header_buffer, 1, 40, musicin); - -  if (wave_header_buffer[8] == 'W' && wave_header_buffer[9] == 'A' -      && wave_header_buffer[10] == 'V' && wave_header_buffer[11] == 'E') { -    fprintf (stderr, "Parsing Wave File Header\n"); -    if (NativeByteOrder == order_unknown) { -      NativeByteOrder = DetermineByteOrder (); -      if (NativeByteOrder == order_unknown) { -        fprintf (stderr, "byte order not determined\n"); -        exit (1); -      } -    } -    if (NativeByteOrder == order_littleEndian) { -      samplerate = wave_header_buffer[24] + -        (wave_header_buffer[25] << 8) + -        (wave_header_buffer[26] << 16) + -        (wave_header_buffer[27] << 24); -    } else { -      samplerate = wave_header_buffer[27] + -        (wave_header_buffer[26] << 8) + -        (wave_header_buffer[25] << 16) + -        (wave_header_buffer[24] << 24); -    } -    /* Wave File */ -    wave_header_read = 1; -    switch (samplerate) { -    case 44100: -    case 48000: -    case 32000: -    case 24000: -    case 22050: -    case 16000: -      fprintf (stderr, ">>> %ld Hz sampling freq selected\n", samplerate); -      break; -    default: -      /* Unknown Unsupported Frequency */ -      fprintf (stderr, ">>> Unknown samp freq %ld Hz in Wave Header\n", -               samplerate); -      fprintf (stderr, ">>> Default 44.1 kHz samp freq selected\n"); -      samplerate = 44100; +    IFF_AIFF pcm_aiff_data; +    long soundPosition; + +    unsigned char wave_header_buffer[40]; //HH fixed +    int wave_header_read = 0; +    int wave_header_stereo = -1; +    int wave_header_16bit = -1; +    unsigned long samplerate; + +    /*************************** STDIN ********************************/ +    /* check if we're reading from stdin. Assume it's a raw PCM file. */ +    /* Of course, you could be piping a WAV file into stdin. Not done in this code */ +    /* this code is probably very dodgy and was written to suit my needs. MFC Dec 99 */ +    if ((strcmp (inPath, "/dev/stdin") == 0)) { +        fprintf (stderr, "Reading from stdin\n"); +        fprintf (stderr, "Remember to set samplerate with '-s'.\n"); +        *num_samples = MAX_U_32_NUM;    /* huge sound file */ +        return;      } -    if ((header->sampling_frequency = -         SmpFrqIndex ((long) samplerate, &header->version)) < 0) { -      fprintf (stderr, "invalid sample rate\n"); -      exit (0); +    /****************************  AIFF ********************************/ +    if ((soundPosition = aiff_read_headers (musicin, &pcm_aiff_data)) != -1) { +        fprintf (stderr, ">>> Using Audio IFF sound file headers\n"); +        aiff_check (inPath, &pcm_aiff_data, &header->version); +        if (fseek (musicin, soundPosition, SEEK_SET) != 0) { +            fprintf (stderr, "Could not seek to PCM sound data in \"%s\".\n", +                    inPath); +            exit (1); +        } +        fprintf (stderr, "Parsing AIFF audio file \n"); +        header->sampling_frequency = +            SmpFrqIndex ((long) pcm_aiff_data.sampleRate, &header->version); +        fprintf (stderr, ">>> %f Hz sampling frequency selected\n", +                pcm_aiff_data.sampleRate); + +        /* Determine number of samples in sound file */ +        *num_samples = pcm_aiff_data.numChannels * pcm_aiff_data.numSampleFrames; + +        if (pcm_aiff_data.numChannels == 1) { +            header->mode = MPG_MD_MONO; +            header->mode_ext = 0; +        } +        return;      } -    if ((long) wave_header_buffer[22] == 1) { -      fprintf (stderr, ">>> Input Wave File is Mono\n"); -      wave_header_stereo = 0; -      header->mode = MPG_MD_MONO; -      header->mode_ext = 0; -    } -    if ((long) wave_header_buffer[22] == 2) { -      fprintf (stderr, ">>> Input Wave File is Stereo\n"); -      wave_header_stereo = 1; +    /**************************** WAVE *********************************/ +    /*   Nick Burch <The_Leveller@newmail.net> */ +    /*********************************/ +    /* Wave File Headers:   (Dec)    */ +    /* 8-11 = "WAVE"                 */ +    /* 22 = Stereo / Mono            */ +    /*       01 = mono, 02 = stereo  */ +    /* 24 = Sampling Frequency       */ +    /* 32 = Data Rate                */ +    /*       01 = x1 (8bit Mono)     */ +    /*       02 = x2 (8bit Stereo or */ +    /*                16bit Mono)    */ +    /*       04 = x4 (16bit Stereo)  */ +    /*********************************/ + +    fseek (musicin, 0, SEEK_SET); +    fread (wave_header_buffer, 1, 40, musicin); + +    if (wave_header_buffer[8] == 'W' && wave_header_buffer[9] == 'A' +            && wave_header_buffer[10] == 'V' && wave_header_buffer[11] == 'E') { +        fprintf (stderr, "Parsing Wave File Header\n"); +        if (NativeByteOrder == order_unknown) { +            NativeByteOrder = DetermineByteOrder (); +            if (NativeByteOrder == order_unknown) { +                fprintf (stderr, "byte order not determined\n"); +                exit (1); +            } +        } +        if (NativeByteOrder == order_littleEndian) { +            samplerate = wave_header_buffer[24] + +                (wave_header_buffer[25] << 8) + +                (wave_header_buffer[26] << 16) + +                (wave_header_buffer[27] << 24); +        } else { +            samplerate = wave_header_buffer[27] + +                (wave_header_buffer[26] << 8) + +                (wave_header_buffer[25] << 16) + +                (wave_header_buffer[24] << 24); +        } +        /* Wave File */ +        wave_header_read = 1; +        switch (samplerate) { +            case 44100: +            case 48000: +            case 32000: +            case 24000: +            case 22050: +            case 16000: +                fprintf (stderr, ">>> %ld Hz sampling freq selected\n", samplerate); +                break; +            default: +                /* Unknown Unsupported Frequency */ +                fprintf (stderr, ">>> Unknown samp freq %ld Hz in Wave Header\n", +                        samplerate); +                fprintf (stderr, ">>> Default 44.1 kHz samp freq selected\n"); +                samplerate = 44100; +        } + +        if ((header->sampling_frequency = +                    SmpFrqIndex ((long) samplerate, &header->version)) < 0) { +            fprintf (stderr, "invalid sample rate\n"); +            exit (0); +        } + +        if ((long) wave_header_buffer[22] == 1) { +            fprintf (stderr, ">>> Input Wave File is Mono\n"); +            wave_header_stereo = 0; +            header->mode = MPG_MD_MONO; +            header->mode_ext = 0; +        } +        if ((long) wave_header_buffer[22] == 2) { +            fprintf (stderr, ">>> Input Wave File is Stereo\n"); +            wave_header_stereo = 1; +        } +        if ((long) wave_header_buffer[32] == 1) { +            fprintf (stderr, ">>> Input Wave File is 8 Bit\n"); +            wave_header_16bit = 0; +            fprintf (stderr, "Input File must be 16 Bit! Please Re-sample"); +            exit (1); +        } +        if ((long) wave_header_buffer[32] == 2) { +            if (wave_header_stereo == 1) { +                fprintf (stderr, ">>> Input Wave File is 8 Bit\n"); +                wave_header_16bit = 0; +                fprintf (stderr, "Input File must be 16 Bit! Please Re-sample"); +                exit (1); +            } else { +                /* fprintf(stderr,  ">>> Input Wave File is 16 Bit\n" ); */ +                wave_header_16bit = 1; +            } +        } +        if ((long) wave_header_buffer[32] == 4) { +            /* fprintf(stderr,  ">>> Input Wave File is 16 Bit\n" ); */ +            wave_header_16bit = 1; +        } +        /* should probably use the wave header to determine size here FIXME MFC Feb 2003 */ +        *num_samples = MAX_U_32_NUM; +        if (fseek (musicin, 44, SEEK_SET) != 0) {   /* there's a way of calculating the size of the +                                                       wave header. i'll just jump 44 to start with */ +            fprintf (stderr, "Could not seek to PCM sound data in \"%s\".\n", +                    inPath); +            exit (1); +        } +        return;      } -    if ((long) wave_header_buffer[32] == 1) { -      fprintf (stderr, ">>> Input Wave File is 8 Bit\n"); -      wave_header_16bit = 0; -      fprintf (stderr, "Input File must be 16 Bit! Please Re-sample"); -      exit (1); -    } -    if ((long) wave_header_buffer[32] == 2) { -      if (wave_header_stereo == 1) { -        fprintf (stderr, ">>> Input Wave File is 8 Bit\n"); -        wave_header_16bit = 0; -        fprintf (stderr, "Input File must be 16 Bit! Please Re-sample"); -        exit (1); -      } else { -        /* fprintf(stderr,  ">>> Input Wave File is 16 Bit\n" ); */ -        wave_header_16bit = 1; -      } -    } -    if ((long) wave_header_buffer[32] == 4) { -      /* fprintf(stderr,  ">>> Input Wave File is 16 Bit\n" ); */ -      wave_header_16bit = 1; -    } -    /* should probably use the wave header to determine size here FIXME MFC Feb 2003 */ + +    /*************************** PCM **************************/ +    fprintf (stderr, "No header found. Assuming Raw PCM sound file\n"); +    /* Raw PCM. No header. Reset the input file to read from the start */ +    fseek (musicin, 0, SEEK_SET); +    /* Assume it is a huge sound file since there's no real info available */ +    /* FIXME: Could always fstat the file? Probably not worth it. MFC Feb 2003 */      *num_samples = MAX_U_32_NUM; -    if (fseek (musicin, 44, SEEK_SET) != 0) {   /* there's a way of calculating the size of the -                                                   wave header. i'll just jump 44 to start with */ -      fprintf (stderr, "Could not seek to PCM sound data in \"%s\".\n", -               inPath); -      exit (1); -    } -    return; -  } - -  /*************************** PCM **************************/ -  fprintf (stderr, "No header found. Assuming Raw PCM sound file\n"); -  /* Raw PCM. No header. Reset the input file to read from the start */ -  fseek (musicin, 0, SEEK_SET); -  /* Assume it is a huge sound file since there's no real info available */ -  /* FIXME: Could always fstat the file? Probably not worth it. MFC Feb 2003 */ -  *num_samples = MAX_U_32_NUM;  }  /************************************************************************ -* -* aiff_check -* -* PURPOSE:  Checks AIFF header information to make sure it is valid. -*           Exits if not. -* -************************************************************************/ + * + * aiff_check + * + * PURPOSE:  Checks AIFF header information to make sure it is valid. + *           Exits if not. + * + ************************************************************************/  void aiff_check (char *file_name, IFF_AIFF * pcm_aiff_data, int *version)  { -  if (pcm_aiff_data->sampleType != IFF_ID_SSND) { -    fprintf (stderr, "Sound data is not PCM in \"%s\".\n", file_name); -    exit (1); -  } - -  if (SmpFrqIndex ((long) pcm_aiff_data->sampleRate, version) < 0) { -    fprintf (stderr, "in \"%s\".\n", file_name); -    exit (1); -  } - -  if (pcm_aiff_data->sampleSize != sizeof (short) * BITS_IN_A_BYTE) { -    fprintf (stderr, "Sound data is not %d bits in \"%s\".\n", -             sizeof (short) * BITS_IN_A_BYTE, file_name); -    exit (1); -  } - -  if (pcm_aiff_data->numChannels != MONO -      && pcm_aiff_data->numChannels != STEREO) { -    fprintf (stderr, "Sound data is not mono or stereo in \"%s\".\n", -             file_name); -    exit (1); -  } - -  if (pcm_aiff_data->blkAlgn.blockSize != 0) { -    fprintf (stderr, "Block size is not %d bytes in \"%s\".\n", 0, file_name); -    exit (1); -  } - -  if (pcm_aiff_data->blkAlgn.offset != 0) { -    fprintf (stderr, "Block offset is not %d bytes in \"%s\".\n", 0, -             file_name); -    exit (1); -  } +    if (pcm_aiff_data->sampleType != IFF_ID_SSND) { +        fprintf (stderr, "Sound data is not PCM in \"%s\".\n", file_name); +        exit (1); +    } + +    if (SmpFrqIndex ((long) pcm_aiff_data->sampleRate, version) < 0) { +        fprintf (stderr, "in \"%s\".\n", file_name); +        exit (1); +    } + +    if (pcm_aiff_data->sampleSize != sizeof (short) * BITS_IN_A_BYTE) { +        fprintf (stderr, "Sound data is not %zu bits in \"%s\".\n", +                sizeof (short) * BITS_IN_A_BYTE, file_name); +        exit (1); +    } + +    if (pcm_aiff_data->numChannels != MONO +            && pcm_aiff_data->numChannels != STEREO) { +        fprintf (stderr, "Sound data is not mono or stereo in \"%s\".\n", +                file_name); +        exit (1); +    } + +    if (pcm_aiff_data->blkAlgn.blockSize != 0) { +        fprintf (stderr, "Block size is not %d bytes in \"%s\".\n", 0, file_name); +        exit (1); +    } + +    if (pcm_aiff_data->blkAlgn.offset != 0) { +        fprintf (stderr, "Block offset is not %d bytes in \"%s\".\n", 0, +                file_name); +        exit (1); +    }  } diff --git a/audio_read.h b/audio_read.h index 7ab3f01..ab17a8f 100644 --- a/audio_read.h +++ b/audio_read.h @@ -28,6 +28,10 @@ typedef struct IFF_AIFF_struct  }  IFF_AIFF; +void setup_jack(frame_header *header, const char* jackname); +int process(jack_nframes_t nframes, void *arg); +void jack_shutdown(void *arg); +  void parse_input_file (FILE *musicin, char *, frame_header *header, unsigned long *num_samples);  void aiff_check (char *file_name, IFF_AIFF * pcm_aiff_data, int *version); @@ -35,7 +39,8 @@ int aiff_read_headers (FILE *, IFF_AIFF *);  int aiff_seek_to_sound_data (FILE *);  enum byte_order DetermineByteOrder (void);  void SwapBytesInWords (short *loc, int words); - unsigned long read_samples (FILE *, short[2304], unsigned long, + unsigned long read_samples (music_in_t*, short[2304], unsigned long,  				   unsigned long); - unsigned long get_audio (FILE *, short[2][1152], unsigned long, + unsigned long get_audio (music_in_t*, short[2][1152], unsigned long,  				int, frame_header *header); + @@ -89,6 +89,7 @@  #include <stdio.h>  #include <stdlib.h> +#include <jack/jack.h>  /* Structure for Reading Layer II Allocation Tables from File */ @@ -162,6 +163,17 @@ enum byte_order  { order_unknown, order_bigEndian, order_littleEndian };  extern enum byte_order NativeByteOrder; + +typedef struct music_in_s +{ +    /* Data for the wav input */ +    FILE* wav_input; + +    /* Data for the jack input */ +    jack_client_t* jack_client; +    const char*    jack_name; +} music_in_t; +  /* "bit_stream.h" Type Definitions */ @@ -16,6 +16,7 @@ typedef struct    float athlevel;                 /* 0      extra argument to the ATH equation -   				          used for VBR in LAME */    int verbosity;                /* 2 by default. 0 is no output at all */ +  int enable_jack; /* 1=use JACK input, 2=use wav input */  }  options; @@ -1,6 +1,9 @@  #include <stdio.h>  #include <stdlib.h>  #include <string.h> +#include <pthread.h> +#include <jack/jack.h> +#include <jack/ringbuffer.h>  #include "common.h"  #include "encoder.h"  #include "musicin.h" @@ -24,7 +27,7 @@  #include <assert.h> -FILE *musicin; +music_in_t musicin;  Bit_stream_struc bs;  char *programName;  char toolameversion[] = "0.2l-opendigitalradio"; @@ -44,6 +47,7 @@ void global_init (void)      glopts.vbrlevel = 0;      glopts.athlevel = 0;      glopts.verbosity = 2; +    glopts.enable_jack = 0;  }  /************************************************************************ @@ -194,7 +198,7 @@ int main (int argc, char **argv)      nch = frame.nch;      error_protection = header.error_protection; -    while (get_audio (musicin, buffer, num_samples, nch, &header) > 0) { +    while (get_audio (&musicin, buffer, num_samples, nch, &header) > 0) {          if (glopts.verbosity > 1)              if (++frameNum % 10 == 0) {                  if (mot_file) { @@ -535,9 +539,11 @@ int main (int argc, char **argv)              (FLOAT) sentBits / (frameNum * 1152) *              s_freq[header.version][header.sampling_frequency]); -    if (fclose (musicin) != 0) { -        fprintf (stderr, "Could not close \"%s\".\n", original_file_name); -        exit (2); +    if (!glopts.enable_jack) { +        if ( fclose (musicin.wav_input) != 0) { +            fprintf (stderr, "Could not close \"%s\".\n", original_file_name); +            exit (2); +        }      }      fprintf (stderr, "\nDone\n"); @@ -561,9 +567,16 @@ void print_config (frame_info * frame, int *psy, char *inPath,          return;      fprintf (stderr, "--------------------------------------------\n"); -    fprintf (stderr, "Input File : '%s'   %.1f kHz\n", -            (strcmp (inPath, "-") ? inPath : "stdin"), -            s_freq[header->version][header->sampling_frequency]); +    if (glopts.enable_jack) { +        fprintf (stderr, "Input JACK\n"); +        fprintf (stderr, "      name %s\n", musicin.jack_name); +    } +    else { +        fprintf (stderr, "Input File : '%s'   %.1f kHz\n", +                (strcmp (inPath, "-") ? inPath : "stdin"), +                s_freq[header->version][header->sampling_frequency]); +    } +      fprintf (stderr, "Output File: '%s'\n",              (strcmp (outPath, "-") ? outPath : "stdout"));      fprintf (stderr, "%d kbps ", bitrate[header->version][header->bitrate_index]); @@ -620,6 +633,7 @@ void usage (void)      fprintf (stdout, "\t-a       downmix from stereo to mono\n");      fprintf (stdout, "\t-x       force byte-swapping of input\n");      fprintf (stdout, "\t-g       swap channels of input file\n"); +    fprintf (stdout, "\t-j       enable jack input\n");      fprintf (stdout, "Output\n");      fprintf (stdout, "\t-m mode  channel mode : s/d/j/m   (dflt %4c)\n",              DFLT_MOD); @@ -670,7 +684,7 @@ void short_usage (void)      fprintf (stderr, "tooLAME version %s\n (http://opendigitalradio.org)\n",              toolameversion);      fprintf (stderr, "MPEG Audio Layer II encoder for DAB\n\n"); -    fprintf (stderr, "USAGE: %s [options] <infile> [outfile]\n\n", programName); +    fprintf (stderr, "USAGE: %s [options] (<infile>|<jackname>) [outfile]\n\n", programName);      fprintf (stderr, "Try \"%s -h\" for more information.\n", programName);      exit (0);  } @@ -686,6 +700,7 @@ void short_usage (void)   * SEMANTICS:  The command line is parsed according to the following   * syntax:   * + * -j  turns on JACK input   * -m  is followed by the mode   * -y  is followed by the psychoacoustic model number   * -s  is followed by the sampling rate @@ -832,6 +847,10 @@ void parse_args (int argc, char **argv, frame_info * frame, int *psy,                              err = 1;                          break; +                    case 'j': +                        glopts.enable_jack = 1; +                        break; +                      case 'b':                          argUsed = 1;                          brate = atoi (arg); @@ -958,23 +977,34 @@ void parse_args (int argc, char **argv, frame_info * frame, int *psy,      } -    if (err || inPath[0] == '\0') -        usage ();			/* If no infile defined, or err has occured, then call usage() */ +    if (err) +        usage ();			/* If err has occured, then call usage() */ + +    if (!glopts.enable_jack && inPath[0] == '\0') +        usage ();			/* If not in jack-mode and no file specified, then call usage() */      if (outPath[0] == '\0') {          /* replace old extension with new one, 1992-08-19, 1995-06-12 shn */          new_ext (inPath, DFLT_EXT, outPath);      } -    if (!strcmp (inPath, "-")) { -        musicin = stdin;		/* read from stdin */ +    if (glopts.enable_jack) { +        musicin.jack_name = inPath;          *num_samples = MAX_U_32_NUM; -    } else { -        if ((musicin = fopen (inPath, "rb")) == NULL) { -            fprintf (stderr, "Could not find \"%s\".\n", inPath); -            exit (1); + +        setup_jack(header, musicin.jack_name); +    } +    else { +        if (!strcmp (inPath, "-")) { +            musicin.wav_input = stdin;		/* read from stdin */ +            *num_samples = MAX_U_32_NUM; +        } else { +            if ((musicin.wav_input = fopen (inPath, "rb")) == NULL) { +                fprintf (stderr, "Could not find \"%s\".\n", inPath); +                exit (1); +            } +            parse_input_file (musicin.wav_input, inPath, header, num_samples);          } -        parse_input_file (musicin, inPath, header, num_samples);      }      /* check for a valid bitrate */ @@ -12,5 +12,5 @@ void print_config (frame_info *, int *,  void usage (void); -  void smr_dump(double smr[2][SBLIMIT], int nch); + | 
