diff options
| author | Matthias P. Braendli <matthias.braendli@mpb.li> | 2014-03-09 15:48:56 +0100 | 
|---|---|---|
| committer | Matthias P. Braendli <matthias.braendli@mpb.li> | 2014-03-09 15:48:56 +0100 | 
| commit | 8e34d9a78752f3a7d8d49adbb219f51da4b2702e (patch) | |
| tree | 26b77f0ca7a3177a9096bb116d7ead50eaa4dc9f /src | |
| parent | 6971dbeba89788773caeffc863ebe3bc5fd652f6 (diff) | |
| download | ODR-AudioEnc-8e34d9a78752f3a7d8d49adbb219f51da4b2702e.tar.gz ODR-AudioEnc-8e34d9a78752f3a7d8d49adbb219f51da4b2702e.tar.bz2 ODR-AudioEnc-8e34d9a78752f3a7d8d49adbb219f51da4b2702e.zip | |
Get drift-canceling encoder to work
Diffstat (limited to 'src')
| -rw-r--r-- | src/AlsaDabplus.cpp | 80 | ||||
| -rw-r--r-- | src/SampleQueue.h | 102 | 
2 files changed, 119 insertions, 63 deletions
| diff --git a/src/AlsaDabplus.cpp b/src/AlsaDabplus.cpp index 50dcddc..103a4b2 100644 --- a/src/AlsaDabplus.cpp +++ b/src/AlsaDabplus.cpp @@ -245,7 +245,7 @@ int main(int argc, char *argv[]) {      uint8_t input_buf[input_size]; -    int max_size = input_size + NUM_SAMPLES_PER_CALL; +    int max_size = 2*input_size + NUM_SAMPLES_PER_CALL;      SampleQueue<uint8_t> queue(BYTES_PER_SAMPLE, channels, max_size); @@ -266,12 +266,6 @@ int main(int argc, char *argv[]) {      fprintf(stderr, "Start ALSA capture thread\n");      alsa_in.start(); -    fprintf(stderr, "Starting queue preroll\n"); -    // Preroll until queue full -    while (queue.size() < input_size) { -        usleep(1000); -    } -      int outbuf_size = subchannel_index*120;      uint8_t outbuf[20480]; @@ -282,10 +276,10 @@ int main(int argc, char *argv[]) {      fprintf(stderr, "Starting encoding\n");      int send_error_count = 0; -    struct timespec tp; -    clock_gettime(CLOCK_MONOTONIC, &tp); +    struct timespec tp_next; +    clock_gettime(CLOCK_MONOTONIC, &tp_next); -    int calls; +    int calls = 0; // for checking      while (1) {          int in_identifier = IN_AUDIO_DATA;          int out_identifier = OUT_BITSTREAM_DATA; @@ -297,20 +291,53 @@ int main(int argc, char *argv[]) {          int in_size, in_elem_size;          int out_size, out_elem_size; + +        // -------------- wait the right amount of time +        struct timespec tp_now; +        clock_gettime(CLOCK_MONOTONIC, &tp_now); + +        unsigned long time_now  = (1000000000ul * tp_now.tv_sec) + +            tp_now.tv_nsec; +        unsigned long time_next = (1000000000ul * tp_next.tv_sec) + +            tp_next.tv_nsec; + +        const unsigned long wait_time = 120000000ul / 2; + +        unsigned long waiting = wait_time - (time_now - time_next); +        if ((time_now - time_next) < wait_time) { +            //printf("Sleep %zuus\n", waiting / 1000); +            usleep(waiting / 1000); +        } + +        // Move our time_counter 60ms into the future. +        // The encoder needs two calls for one frame +        tp_next.tv_nsec += wait_time; +        if (tp_next.tv_nsec >  1000000000L) { +            tp_next.tv_nsec -= 1000000000L; +            tp_next.tv_sec  += 1; +        } + + +        // -------------- Read Data          memset(outbuf, 0x00, outbuf_size); -        int read = queue.pop(input_buf, input_size); +        size_t overruns; +        size_t read = queue.pop(input_buf, input_size, &overruns); // returns bytes          if (read != input_size) { -            fprintf(stderr, "Short read\n"); +            fprintf(stderr, "U"); +        } + +        if (overruns) { +            fprintf(stderr, "O%zu", overruns);          }          // -------------- AAC Encoding          in_ptr = input_buf; -        in_size = read; +        in_size = (int)read;          in_elem_size = BYTES_PER_SAMPLE; -        in_args.numInSamples = input_size; +        in_args.numInSamples = input_size/BYTES_PER_SAMPLE;          in_buf.numBufs = 1;          in_buf.bufs = &in_ptr;          in_buf.bufferIdentifiers = &in_identifier; @@ -334,14 +361,15 @@ int main(int argc, char *argv[]) {              fprintf(stderr, "Encoding failed\n");              break;          } -          calls++;          /* Check if the encoder has generated output data */          if (out_args.numOutBytes != 0)          { -            fprintf(stderr, "data out after %d calls\n", calls); +            // Our timing code depends on this +            assert (calls == 2);              calls = 0; +              // ----------- RS encoding              int row, col;              unsigned char buf_to_rs_enc[110]; @@ -377,26 +405,6 @@ int main(int argc, char *argv[]) {              if (out_args.numOutBytes + row*10 == outbuf_size)                  fprintf(stderr, ".");          } - -        // -------------- wait the right amount of time -        tp.tv_nsec += 60000000; -        if (tp.tv_nsec >  1000000000L) { -            tp.tv_nsec -= 1000000000L; -            tp.tv_sec  += 1; -        } - -        fprintf(stderr, "sleep %ld.%ld\n", tp.tv_sec, tp.tv_nsec); -        struct timespec tp_now; -        do { -            usleep(1000); -            clock_gettime(CLOCK_MONOTONIC, &tp_now); -        } while (tp_now.tv_sec < tp.tv_sec || -                ( tp_now.tv_sec == tp.tv_sec && -                  tp_now.tv_nsec < tp.tv_nsec) ); - -        tp.tv_sec = tp_now.tv_sec; -        tp.tv_nsec = tp_now.tv_nsec; -      }      zmq_sock.close(); diff --git a/src/SampleQueue.h b/src/SampleQueue.h index eabc301..778526e 100644 --- a/src/SampleQueue.h +++ b/src/SampleQueue.h @@ -9,6 +9,8 @@  #ifndef _SAMPLE_QUEUE_H_  #define _SAMPLE_QUEUE_H_ +#define DEBUG_SAMPLE_QUEUE 0 +  #include <boost/thread.hpp>  #include <queue> @@ -18,10 +20,23 @@   * that pushes elements into the queue, and one consumer that   * retrieves the elements.   * - * The queue can make the consumer block until enough elements - * are available. + * This queue should contain audio sample data, interleaved L/R + * form, 2bytes per sample. Therefore, the push and pop functions + * should always place or retrieve data in multiples of + * bytes_per_sample * number_of_channels + * + * The queue has a maximum size. If this size is reached, push() + * ignores new data. + * + * If pop() is called but there is not enough data in the queue, + * the missing samples are replaced by zeros. pop() will always + * write the requested length.   */ + +/* The template is actually not really tested for anything else + * than uint8_t + */  template<typename T>  class SampleQueue  { @@ -30,7 +45,9 @@ public:              unsigned int channels,              size_t max_size) :          m_bytes_per_sample(bytes_per_sample), -        m_channels(channels), m_max_size(max_size) {} +        m_channels(channels), +        m_max_size(max_size), +        m_overruns(0) {}      /* Push a bunch of samples into the buffer */ @@ -38,10 +55,18 @@ public:      {          boost::mutex::scoped_lock lock(m_mutex); +        assert(len % (m_channels * m_bytes_per_sample) == 0); + +#if DEBUG_SAMPLE_QUEUE +        fprintf(stdout, "######## push %s %zu, %zu >= %zu\n", +                (m_queue.size() >= m_max_size) ? "overrun" : "ok", +                len / 4, +                m_queue.size() / 4, +                m_max_size / 4); +#endif +          if (m_queue.size() >= m_max_size) { -            /*fprintf(stderr, "######## push overrun %zu, %zu\n", -                    len, -                    m_queue.size()); // */ +            m_overruns++;              return 0;          } @@ -50,9 +75,6 @@ public:          }          size_t new_size = m_queue.size(); -        lock.unlock(); - -        //m_condition_variable.notify_one();          return new_size;      } @@ -69,14 +91,36 @@ public:       */      size_t pop(T* buf, size_t len)      { +        size_t ovr; +        return pop(buf, len, ovr); +    } + +    /* Get len elements, place them into the buf array. +     * Also update the overrun variable with the information +     * of how many overruns we saw since the last pop. +     * Returns the number of elements it was able to take +     * from the queue +     */ +    size_t pop(T* buf, size_t len, size_t* overruns) +    {          boost::mutex::scoped_lock lock(m_mutex); -        fprintf(stderr, "######## pop %zu (%zu)\n", -                len, -                m_queue.size()); + +        assert(len % (m_channels * m_bytes_per_sample) == 0); + +#if DEBUG_SAMPLE_QUEUE +        fprintf(stdout, "######## pop %zu (%zu), %zu overruns: ", +                len / 4, +                m_queue.size() / 4, +                m_overruns); +#endif +        *overruns = m_overruns; +        m_overruns = 0;          size_t ret = 0;          if (m_queue.size() < len) { +            /* Not enough data in queue, fill with zeros */ +              size_t i;              for (i = 0; i < m_queue.size(); i++) {                  buf[i] = m_queue[i]; @@ -89,8 +133,16 @@ public:              }              m_queue.resize(0); + +#if DEBUG_SAMPLE_QUEUE +            fprintf(stdout, "after short pop %zu (%zu)\n", +                len / 4, +                m_queue.size() / 4); +#endif          }          else { +            /* Queue contains enough data */ +              for (size_t i = 0; i < len; i++) {                  buf[i] = m_queue[i];              } @@ -98,33 +150,29 @@ public:              ret = len;              m_queue.erase(m_queue.begin(), m_queue.begin() + len); -        } - -        return ret; -    } -    /* -    void wait_and_pop(T& popped_value) -    { -        boost::mutex::scoped_lock lock(m_mutex); -        while(m_queue.size() < m_required_size) -        { -            m_condition_variable.wait(lock); +#if DEBUG_SAMPLE_QUEUE +            fprintf(stdout, "after ok pop %zu (%zu)\n", +                len / 4, +                m_queue.size() / 4); +#endif          } -        popped_value = m_queue.front(); -        m_queue.pop_front(); +        return ret;      } -    */  private:      std::deque<T> m_queue;      mutable boost::mutex m_mutex; -    //boost::condition_variable m_condition_variable;      unsigned int m_channels;      unsigned int m_bytes_per_sample;      size_t m_max_size; + +    /* Counter to keep track of number of overruns between calls +     * to pop() +     */ +    size_t m_overruns;  };  #endif | 
