General clean-up.
authorbruceperens <bruceperens@01035d8c-6547-0410-b346-abe4f91aad63>
Tue, 11 Mar 2014 19:37:34 +0000 (19:37 +0000)
committerbruceperens <bruceperens@01035d8c-6547-0410-b346-abe4f91aad63>
Tue, 11 Mar 2014 19:37:34 +0000 (19:37 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@1426 01035d8c-6547-0410-b346-abe4f91aad63

freedv-server/source/big_main.cpp
freedv-server/source/drivers.h
freedv-server/source/fifo.cpp
freedv-server/source/interfaces.cpp
freedv-server/source/modem_noop.cpp
freedv-server/source/platform/linux/audio_out_alsa.cpp
freedv-server/source/run.cpp
freedv-server/source/test/fifo.cpp

index 86657dd165af98742d05144bce70e65b5ae6ef07..7ba58c57a07daa22ea4876147cbe43527a389927 100644 (file)
@@ -100,6 +100,19 @@ main(int argc, char * * argv)
     int command;
     while ((command = getopt_long(argc, argv, "c:Cdf:hi:k:l:m:M:p:P:r:t:x:", options, NULL)) != -1 ) {
       switch (command) {
+      case 0:
+        break;
+      case 'd':
+        drivers();
+        exit(0);
+      default:
+      case 'h':
+        help(argv[0]);
+        exit(1);
+      case 'C':
+       // FIX: Operator overload doesn't work here.
+        i.print(cout, argv[0]) << endl;
+        exit(0);
       case 'c':
       case 'f':
       case 'i':
@@ -123,20 +136,14 @@ main(int argc, char * * argv)
   
         Base * set = (Base *)1; 
   
+
         switch (command) {
         case 'c':
           set = i.codec = m->codec(driver, parameter);
           break;
-        case 'd':
-          drivers();
-          exit(0);
         case 'f':
           set = i.framer = m->framer(driver, parameter);
           break;
-        default:
-        case 'h':
-          help(argv[0]);
-          exit(1);
         case 'i':
           set = i.user_interface = m->user_interface(driver, parameter, &i);
           break;
@@ -167,12 +174,6 @@ main(int argc, char * * argv)
         case 'x':
           set = i.text_input = m->text_input(driver, parameter);
           break;
-        case 'C':
-       // FIX: Operator overload doesn't work here.
-          i.print(cout) << endl;
-          exit(0);
-        case 0:
-          break;
         }
         if ( set == 0 )
           exit(1);
index 4f1ca9cec6b8c1e77158fb1ae5ea0010ccf2517f..fb7f954ee9ded55508c8484b2b0e54e3e7389bdc 100644 (file)
@@ -32,7 +32,7 @@ namespace FreeDV {
     uint8_t *                  in;
     const uint8_t *            out;
 
-    void       out_overrun() const;
+    void       get_overrun() const;
     uint8_t *  reorder(std::size_t length);
 
   public:
@@ -42,9 +42,36 @@ namespace FreeDV {
 
                        ~FIFO();
 
+    /// Returns the amount of data available to read.
+    /// \return The amount of data, in bytes, available to read.
+    inline std::size_t get_available() const {
+                         return in - out;
+                       }
+
+    /// Return the address of output data of the requested length.
+    /// \param length The amount of data requested. This must be smaller
+    /// than or equal to the amount returned by get_available().
+    /// \return The address of the data to be read.
+    inline const uint8_t *     get(std::size_t length) {
+                         if ( length > (std::size_t)(in - out) )
+                           get_overrun();
+                         return out;
+                       }
+
+    /// Finish the I/O after get().
+    /// \param length The amount of data, in bytes, actually read.
+    /// This must be smaller than or equal to the amount passed to
+    /// get().
+    inline void                get_done(std::size_t length) {
+                         out += length;
+                         assert(out >= buffer && out <= buffer_end);
+                         if ( out == in )
+                           out = in = buffer;
+                       }
+
     /// Returns the amount of space available for incoming data.
     /// \return The amount of space, in bytes, available for incoming data.
-    inline std::size_t incoming_available() const {
+    inline std::size_t put_space() const {
                          return (buffer_end) - in + (out - buffer);
                        }
 
@@ -52,12 +79,12 @@ namespace FreeDV {
     /// Throws an error if we run the buffer out of space. Well-behaved code
     /// won't allocate a size that can't be drained before it is further
     /// written.
-    /// You must call incoming_done(length) when the I/O is completed.
-    /// The length passed to incoming_done() must be smaller than or equal
-    /// to the length passed to incoming_buffer().
+    /// You must call put_done(length) when the I/O is completed.
+    /// The length passed to put_done() must be smaller than or equal
+    /// to the length passed to put().
     /// \param io_length The size of buffer in chars requested.
     /// \return The address of the buffer for incoming data.
-    inline uint8_t *   incoming_buffer(std::size_t io_length) {
+    inline uint8_t *   put(std::size_t io_length) {
                          const uint8_t * io_end = in + io_length;
 
                          if ( io_end > buffer_end )
@@ -66,39 +93,14 @@ namespace FreeDV {
                            return in;
                        }
 
-    /// Complete the I/O after incoming_buffer().
+    /// Complete the I/O after put().
     /// \param length The amount of data actually written. This must be
-    /// smaller than or equal to the length passed to incoming_buffer().
-    inline void                incoming_done(std::size_t length) {
+    /// smaller than or equal to the length passed to put().
+    inline void                put_done(std::size_t length) {
                          in += length;
                          assert(in >= buffer && in <= buffer_end);
                        }
 
-    /// Returns the amount of data available to read.
-    /// \return The amount of data, in bytes, available to read.
-    inline std::size_t outgoing_available() const {
-                         return in - out;
-                       }
-
-    /// Return the address of output data of the requested length.
-    /// \param length The amount of data requested. This must be smaller
-    /// than or equal to the amount returned by outgoing_available().
-    /// \return The address of the data to be read.
-    inline const uint8_t *     outgoing_buffer(std::size_t length) {
-                         if ( length > (std::size_t)(in - out) )
-                           out_overrun();
-                         return out;
-                       }
-
-    /// Finish the I/O after outgoing_buffer().
-    /// \param length The amount of data, in bytes, actually read.
-    /// This must be smaller than or equal to the amount passed to
-    /// outgoing_buffer().
-    inline void                outgoing_done(std::size_t length) {
-                         out += length;
-                         assert(out >= buffer && out <= buffer_end);
-                       }
-
     /// Discard any buffered data.
     void               reset();
   };
@@ -689,7 +691,7 @@ namespace FreeDV {
     /// \return A reference to the provided stream, meant for the
     ///  usual successive call paradigm of ostream operator << .
     virtual std::ostream &
-                       print(std::ostream & stream) const;
+                       print(std::ostream & stream, const char * program_name) const;
   };
 
   /// Write the driver information from the Interfaces object onto a stream,
@@ -702,7 +704,7 @@ namespace FreeDV {
   ///  usual successive call paradigm of ostream operator << .
   inline std::ostream &
   operator << (std::ostream & stream, const Interfaces & interfaces) {
-    return interfaces.print(stream);
+    return interfaces.print(stream, 0);
   }
 
   // Most of the functions in the Driver and Enumerator namespaces are
index b498bfa9aa2a4e77dfe37583884f4d7e7b76803c..1e539784af5370306be5169fca9cc75b95caf4b0 100644 (file)
@@ -15,7 +15,7 @@ namespace FreeDV {
   }
 
   void
-  FIFO::out_overrun() const
+  FIFO::get_overrun() const
   {
     throw std::runtime_error("FIFO outgoing data overrun.");
   }
@@ -29,13 +29,6 @@ namespace FreeDV {
 
       // memmove() is specified to handle overlap properly.
       memmove(buffer, out, bytes);
-#ifdef DEBUG
-      std::cerr << "FIFO reorder with copy. Size = " << size
-       << ", buffer = " << (void *)buffer << ", buffer_end = "
-       << (void *)buffer_end << ", in = " << (void *)in
-       << ", out = " << (void *)out
-       << std::endl;
-#endif
     }
     out = buffer;
     in = buffer + bytes;
index 0c47e1e9e95779abfac353bee81da0b155d861d9..a62b74e77c99f2180bc7ef2cd89753bf27fca1bf 100644 (file)
@@ -41,26 +41,29 @@ namespace FreeDV {
       transmitter = Driver::AudioSink(empty);
 
     if ( !receiver )
-      receiver = Driver::Tone(empty);
+      receiver = Driver::Tone("1000,1.0");
 
     if ( !user_interface )
       user_interface = Driver::BlankPanel(empty, this);
   }
 
   std::ostream &
-  Interfaces::print(std::ostream & stream) const
+  Interfaces::print(std::ostream & stream, const char * program_name) const
   {
-    stream << "--codec=" << *codec << std::endl;
-    stream << "--gui=" << *user_interface << std::endl;
-    stream << "--keying=" << *keying_output << std::endl;
-    stream << "--loudspeaker=" << *loudspeaker << std::endl;
-    stream << "--microphone=" << *microphone << std::endl;
-    stream << "--modem=" << *modem << std::endl;
-    stream << "--ptt-digital=" << *ptt_input_digital << std::endl;
-    stream << "--ptt-ssb=" << *ptt_input_ssb << std::endl;
-    stream << "--receiver=" << *receiver << std::endl;
-    stream << "--text=" << *text_input << std::endl;
-    stream << "--transmitter=" << *transmitter << std::endl;
+    if ( program_name ) {
+      stream << program_name << " \\" << std::endl;
+    }
+    stream << "--codec=\"" << *codec << "\" \\" << std::endl;
+    stream << "--gui=\"" << *user_interface << "\" \\" << std::endl;
+    stream << "--keying=\"" << *keying_output << "\" \\" << std::endl;
+    stream << "--loudspeaker=\"" << *loudspeaker << "\" \\" << std::endl;
+    stream << "--microphone=\"" << *microphone << "\" \\" << std::endl;
+    stream << "--modem=\"" << *modem << "\" \\" << std::endl;
+    stream << "--ptt-digital=\"" << *ptt_input_digital << "\" \\" << std::endl;
+    stream << "--ptt-ssb=\"" << *ptt_input_ssb << "\" \\" << std::endl;
+    stream << "--receiver=\"" << *receiver << "\" \\" << std::endl;
+    stream << "--text=\"" << *text_input << "\" \\" << std::endl;
+    stream << "--transmitter=\"" << *transmitter << "\"" << std::endl;
 
     return stream;
   }
index c0eeda04c084a353ae79405ceda3df02bc80e1a3..dedb96e8473fdcfc137f6c770410838ecc2657c8 100644 (file)
@@ -84,6 +84,7 @@ namespace FreeDV {
    std::size_t data_length)
   {
     const std::size_t length = min(data_length / 2, *sample_length);
+
     memcpy(o, i, length * 2);
     *sample_length = length;
     return length;
index 884a1bfb89a733339ffa3a71a5944ee6d86a25fa..fdccc7419057ea6708d424243c2101a8eb9f3ac4 100644 (file)
@@ -1,6 +1,7 @@
 /// The ALSA audio output driver. 
 
 #include <stdlib.h>
+#include <errno.h>
 #include "drivers.h"
 #include <alsa/asoundlib.h>
 #include <sys/ioctl.h>
@@ -89,7 +90,17 @@ namespace FreeDV {
   std::size_t
   AudioOutALSA::write16(const std::int16_t * array, std::size_t length)
   {
-    const int result = snd_pcm_writei(handle, array, length);
+    // for ( std::size_t i = 0 ; i < length ; i++ )
+      // std::cerr << array[i] << ' ';
+
+    int result = snd_pcm_writei(handle, array, length);
+    if ( result == -EPIPE ) {
+      snd_pcm_recover(handle, result, 1);
+      result = snd_pcm_writei(handle, array, length);
+      std::cerr << "ALSA write underrun." << std::endl;
+      if ( result == -EPIPE )
+        return 0;
+    }
     if ( result >= 0 )
       return result;
     else {
@@ -115,10 +126,18 @@ namespace FreeDV {
   {
     snd_pcm_sframes_t  available = 0;
 
-    if ( (available = snd_pcm_avail(handle)) >= 0 )
+    available = snd_pcm_avail(handle);
+    if ( available == -EPIPE ) {
+      snd_pcm_recover(handle, available, 1);
+      available = snd_pcm_avail(handle);
+      std::cerr << "ALSA write underrun." << std::endl;
+    }
+    if ( available >= 0 )
       return available;
+    else if ( available == -EPIPE )
+      return 0;
     else {
-      do_throw(available, "Get Available Frames");
+      do_throw(available, "Get Frames Available for Write");
       return 0; // do_throw doesn't return.
     }
   }
index 252ba07e3f1ca61105e25fc2df7af8301d2c0801..5098a1463223f9f3bc9e2297be28ea28ca2dbe2c 100644 (file)
@@ -28,8 +28,8 @@ namespace FreeDV {
     bool               begin_receive;
     bool               begin_transmit;
     FIFO               codec_fifo;
-    FIFO               input_fifo;
-    FIFO               output_fifo;
+    FIFO               in_fifo;
+    FIFO               out_fifo;
     bool               ptt_digital;
     bool               ptt_ssb;
  
@@ -48,8 +48,8 @@ namespace FreeDV {
   
   Run::Run(Interfaces * interfaces)
   : i(interfaces), begin_receive(true), begin_transmit(false),
-    codec_fifo(TempSize * 2), input_fifo(TempSize * 2),
-    output_fifo(TempSize * 2), ptt_digital(false), ptt_ssb(false)
+    codec_fifo(TempSize * 2), in_fifo(TempSize * 2),
+    out_fifo(TempSize * 2), ptt_digital(false), ptt_ssb(false)
   {
   }
 
@@ -60,9 +60,9 @@ namespace FreeDV {
   void
   Run::reset_fifos()
   {
-    input_fifo.reset();
+    in_fifo.reset();
     codec_fifo.reset();
-    output_fifo.reset();
+    out_fifo.reset();
   }
 
   void
@@ -94,84 +94,78 @@ namespace FreeDV {
   Run::receive()
   {
     // Drain any data that the loudspeaker can take.
-    const std::size_t  output_samples = min(
+    const std::size_t  out_samples = min(
                         i->loudspeaker->ready(),
-                        (output_fifo.outgoing_available() / 2));
+                        (out_fifo.get_available() / 2));
 
-    if ( output_samples ) {
+    if ( out_samples ) {
+        std::int16_t * s = (std::int16_t *)out_fifo.get(out_samples * 2);
+
+        for ( std::size_t i = 0; i < out_samples; i++ ) {
+          std::cerr << (double)s[i] / 32767.0 << ' ';
+       }
       const std::size_t result = i->loudspeaker->write16(
-                                 (std::int16_t *)output_fifo.outgoing_buffer(
-                                  output_samples * 2),
-                                 output_samples);
+                                 (std::int16_t *)out_fifo.get(
+                                  out_samples * 2),
+                                 out_samples);
 
       if ( result > 0 )
-        output_fifo.outgoing_done(result * 2);
+        out_fifo.get_done(result * 2);
       else
        std::cerr << "Loudspeaker I/O error: " << strerror(errno) << std::endl;
     }
     
     // Fill any data that the receiver can provide.
-    const std::size_t  input_samples = min(
+    const std::size_t  in_samples = min(
                         i->receiver->ready(),
-                        (input_fifo.incoming_available() / 2));
+                        (in_fifo.put_space() / 2));
 
-    if ( input_samples ) {
+    if ( in_samples ) {
       const std::size_t result = i->receiver->read16(
-        (std::int16_t *)input_fifo.incoming_buffer(input_samples * 2),
-        input_samples);
+        (std::int16_t *)in_fifo.put(in_samples * 2),
+        in_samples);
 
       if ( result > 0 )
-        input_fifo.incoming_done(result * 2);
+        in_fifo.put_done(result * 2);
       else
-       std::cerr << "Loudspeaker I/O error: " << strerror(errno) << std::endl;
+       std::cerr << "Receiver I/O error: " << strerror(errno) << std::endl;
     }
     
-    const std::size_t  frames_to_demodulate = (codec_fifo.incoming_available()
-                        / i->modem->bytes_per_frame());
-
-    if ( frames_to_demodulate && input_fifo.outgoing_available() > i->modem->bytes_per_frame()) {
-      std::size_t      samples_to_demodulate = input_fifo.outgoing_available()
-                        / 2;
-      const std::size_t        bytes_to_demodulate = frames_to_demodulate
-                        * i->modem->bytes_per_frame();
+    if ( in_fifo.get_available() > 0 ) {
+      std::size_t      samples_to_demodulate = in_fifo.get_available() / 2;
+      const std::size_t        bytes_to_demodulate = codec_fifo.put_space();
 
       std::size_t result = i->modem->demodulate16(
-                           (const std::int16_t *)input_fifo.outgoing_buffer(
+                           (const std::int16_t *)in_fifo.get(
                             samples_to_demodulate * 2),
-                           codec_fifo.incoming_buffer(bytes_to_demodulate),
+                           codec_fifo.put(bytes_to_demodulate),
                            &samples_to_demodulate,
                            bytes_to_demodulate);
 
       if ( samples_to_demodulate > 0 )
-        input_fifo.outgoing_done(samples_to_demodulate * 2);
+        in_fifo.get_done(samples_to_demodulate * 2);
 
       if ( result > 0 )
-        codec_fifo.incoming_done(result);
+        codec_fifo.put_done(result);
     }
 
-    const std::size_t  frames_to_decode = 
-                        (output_fifo.incoming_available() / 2)
-                         / i->codec->samples_per_frame();
-
-    if ( frames_to_decode > 0
-     && codec_fifo.outgoing_available() > i->codec->bytes_per_frame() ) {
-      std::size_t bytes_to_decode = codec_fifo.outgoing_available();
+    if ( codec_fifo.get_available() > 0 ) {
+      std::size_t bytes_to_decode = codec_fifo.get_available();
 
-      const std::size_t samples_to_decode = frames_to_decode \
-                                            * i->codec->samples_per_frame();
+      const std::size_t samples_to_decode = out_fifo.put_space() / 2;
 
       const std::size_t result = i->codec->decode16(
-                                 codec_fifo.outgoing_buffer(bytes_to_decode),
-                                 (std::int16_t *)output_fifo.incoming_buffer(
+                                 codec_fifo.get(bytes_to_decode),
+                                 (std::int16_t *)out_fifo.put(
                                    samples_to_decode * 2),
                                  &bytes_to_decode,
                                  samples_to_decode);
 
       if ( bytes_to_decode > 0 )
-        codec_fifo.outgoing_done(bytes_to_decode);
+        codec_fifo.get_done(bytes_to_decode);
 
       if ( result > 0 )
-        output_fifo.incoming_done(result * 2);
+        out_fifo.put_done(result * 2);
     }
   }
   
index 5333f5f265d3db24e0a721b07a5d2b5c1da78917..7f1c66c24c9bcbcd3edf8734dde29bcece389c97 100644 (file)
@@ -24,58 +24,58 @@ protected:
 };
 
 TEST_F(FIFOTest, CanFillAndDrain) {
-  ASSERT_EQ(100U, f->incoming_available());
-  memset(f->incoming_buffer(100), 255, 100);
-  ASSERT_EQ(0U, f->outgoing_available());
-  f->incoming_done(100);
-  ASSERT_EQ(100U, f->outgoing_available());
-  ASSERT_EQ(0U, f->incoming_available());
-  EXPECT_THROW(f->incoming_buffer(1), std::runtime_error);
-  ASSERT_EQ(100U, f->outgoing_available());
-  ASSERT_NE((uint8_t *)0, f->outgoing_buffer(100));
-  f->outgoing_done(100);
-  ASSERT_EQ(0U, f->outgoing_available());
-  ASSERT_EQ(100U, f->incoming_available());
-  ASSERT_EQ(100U, f->incoming_available());
-  memset(f->incoming_buffer(100), 255, 100);
-  ASSERT_EQ(0U, f->outgoing_available());
-  f->incoming_done(100);
-  ASSERT_EQ(100U, f->outgoing_available());
-  ASSERT_EQ(0U, f->incoming_available());
+  ASSERT_EQ(100U, f->put_space());
+  memset(f->put(100), 255, 100);
+  ASSERT_EQ(0U, f->get_available());
+  f->put_done(100);
+  ASSERT_EQ(100U, f->get_available());
+  ASSERT_EQ(0U, f->put_space());
+  EXPECT_THROW(f->put(1), std::runtime_error);
+  ASSERT_EQ(100U, f->get_available());
+  ASSERT_NE((uint8_t *)0, f->get(100));
+  f->get_done(100);
+  ASSERT_EQ(0U, f->get_available());
+  ASSERT_EQ(100U, f->put_space());
+  ASSERT_EQ(100U, f->put_space());
+  memset(f->put(100), 255, 100);
+  ASSERT_EQ(0U, f->get_available());
+  f->put_done(100);
+  ASSERT_EQ(100U, f->get_available());
+  ASSERT_EQ(0U, f->put_space());
 }
 
 TEST_F(FIFOTest, Reorder) {
   uint8_t * b;
   const uint8_t * r;
 
-  ASSERT_EQ(100U, f->incoming_available());
-  ASSERT_NE((uint8_t *)0, b = f->incoming_buffer(99));
+  ASSERT_EQ(100U, f->put_space());
+  ASSERT_NE((uint8_t *)0, b = f->put(99));
   memset(b, 0, 98);
   b[98] = 'b';
-  f->incoming_done(99);
-  ASSERT_EQ(1U, f->incoming_available());
-  ASSERT_EQ(99U, f->outgoing_available());
-  ASSERT_NE((uint8_t *)0, f->outgoing_buffer(98));
-  f->outgoing_done(98);
-  ASSERT_EQ(1U, f->outgoing_available());
-  ASSERT_EQ(99U, f->incoming_available());
+  f->put_done(99);
+  ASSERT_EQ(1U, f->put_space());
+  ASSERT_EQ(99U, f->get_available());
+  ASSERT_NE((uint8_t *)0, f->get(98));
+  f->get_done(98);
+  ASSERT_EQ(1U, f->get_available());
+  ASSERT_EQ(99U, f->put_space());
   // This should cause reorder().
-  ASSERT_NE((uint8_t *)0, b = f->incoming_buffer(2));
-  f->incoming_done(0);
-  ASSERT_EQ(99U, f->incoming_available());
-  ASSERT_EQ(1U, f->outgoing_available());
-  ASSERT_NE((uint8_t *)0, r = f->outgoing_buffer(1));
+  ASSERT_NE((uint8_t *)0, b = f->put(2));
+  f->put_done(0);
+  ASSERT_EQ(99U, f->put_space());
+  ASSERT_EQ(1U, f->get_available());
+  ASSERT_NE((uint8_t *)0, r = f->get(1));
   ASSERT_EQ('b', *r);
-  f->outgoing_done(1);
+  f->get_done(1);
 }
 
 TEST_F(FIFOTest, CanReset) {
-  ASSERT_EQ(100U, f->incoming_available());
-  ASSERT_EQ(0U, f->outgoing_available());
-  f->incoming_done(100);
-  ASSERT_EQ(100U, f->outgoing_available());
-  ASSERT_EQ(0U, f->incoming_available());
+  ASSERT_EQ(100U, f->put_space());
+  ASSERT_EQ(0U, f->get_available());
+  f->put_done(100);
+  ASSERT_EQ(100U, f->get_available());
+  ASSERT_EQ(0U, f->put_space());
   f->reset();
-  ASSERT_EQ(0U, f->outgoing_available());
-  ASSERT_EQ(100U, f->incoming_available());
+  ASSERT_EQ(0U, f->get_available());
+  ASSERT_EQ(100U, f->put_space());
 }