const unsigned int SampleRate = 48000;
// The minimum frame duration in milliseconds. The audio interfaces will
- // use this as a period size. It should be the smallest frame we expect
- // a modem/protocol/codec combination to use. If it's too large, latency
- // will be overlong.
+ // use one half of this as a period size. It should be the smallest frame
+ // we expect a modem/protocol/codec combination to use. If it's too large,
+ // latency will be overlong.
const unsigned int MinimumFrameDuration = 10;
// The maximum frame duration in milliseconds. The audio interfaces will
- // use 3 times this as a buffer size. It should be the largest frame we
- // expect a modem/protocol/codec combination to use. If it's too large,
- // ALSA bugs surface and cause long delays.
+ // use 2 times this as a buffer size. It must be an integer multiple of
+ // MinimumFrameDuration, or ALSA will complain. It should be the largest
+ // frame we expect a modem/protocol/codec combination to use.
+ // If a modem/framer/codec combination specify a frame duration larger than
+ // this, it's an error.
+ // If it's too large, ALSA bugs surface (Or is it my lack of
+ // understanding?) and cause long delays.
const unsigned int MaximumFrameDuration = 100;
/// Allocate memory and copy a string into it, so that it is permanently
SND_PCM_ACCESS_RW_INTERLEAVED,
1,
SampleRate,
- (int)ceil(((double)SampleRate / 1000.0) * MinimumFrameDuration),
+ (int)ceil(((double)SampleRate / 1000.0) * MinimumFrameDuration / 2),
(int)ceil(((double)SampleRate / 1000.0) * MaximumFrameDuration * 2));
snd_pcm_start(handle);
SND_PCM_ACCESS_RW_INTERLEAVED,
1,
SampleRate,
- period_size,
+ period_size / 2,
(int)ceil(((double)SampleRate / 1000.0) * MaximumFrameDuration));
}
/// The main loop of the program.
#include "drivers.h"
-#include <unistd.h>
#include <iostream>
-#include <fstream>
+#include <sstream>
+#include <stdexcept>
+#include <unistd.h>
#include <string.h>
#include <sys/time.h>
///
namespace FreeDV {
-
class Run {
private:
const std::size_t TempSize = 10240;
void
Run::run()
{
- // The no-op codec, modem, and framer may have very small durations.
- // So we set a minimum here.
- min_frame_duration = 10;
+ min_frame_duration = MinimumFrameDuration;
min_frame_duration = max(min_frame_duration, i->modem->min_frame_duration());
min_frame_duration = max(min_frame_duration, i->codec->min_frame_duration());
min_frame_duration = max(min_frame_duration, i->framer->min_frame_duration());
std::cerr << "minimum frame duration is " << min_frame_duration << std::endl;
+ if ( min_frame_duration > MaximumFrameDuration ) {
+ std::ostringstream str;
+
+ str << "At " << __FILE__ << ":" << __LINE__ << std::endl;
+ str << "min_frame_duration of " << min_frame_duration;
+ str << " is larger than MaximumFrameDuration of ";
+ str << MaximumFrameDuration << '.' << std::endl;
+ str << "A Modem, Framer, or Codec returned min_frame_duration() that";
+ str << " was too large, or MaximumFrameDuration must be increased.";
+ throw std::runtime_error(str.str().c_str());
+ }
assert(min_frame_duration < 1000000);
while ( true ) {