sampleFormat

git-svn-id: svn://elaine/murooma/trunk@205 d8a302eb-03bc-478d-80e4-98257eca68ef
This commit is contained in:
(no author) 2014-08-23 11:40:23 +00:00
parent d4fcf84fb8
commit e7803a2c11
13 changed files with 176 additions and 157 deletions

View file

@ -3,7 +3,7 @@ CC = /usr/bin/g++
CFLAGS = -std=gnu++0x -Wall -Wno-unused-function -O3 -D_REENTRANT -DVERSION=\"$(VERSION)\" -I..
LDFLAGS = -lrt -lpthread -lportaudio -lboost_system -lboost_program_options -lasound
OBJ = snapClient.o stream.o ../common/chunk.o ../common/log.o
OBJ = snapClient.o stream.o ../common/chunk.o ../common/log.o ../common/sampleFormat.o
BIN = snapclient
all: client

View file

@ -19,6 +19,7 @@
#include <boost/program_options.hpp>
#include <alsa/asoundlib.h>
#include "common/sampleFormat.h"
#include "common/chunk.h"
#include "common/utils.h"
#include "common/log.h"
@ -30,9 +31,6 @@ namespace po = boost::program_options;
int deviceIdx;
uint16_t sampleRate;
short channels;
uint16_t bps;
Stream* stream;
#define PCM_DEVICE "default"
@ -52,7 +50,7 @@ void socketRead(tcp::socket* socket, void* to, size_t bytes)
void receiver(const std::string& ip, int port)
void receiver(const SampleFormat& format, const std::string& ip, int port)
{
try
{
@ -78,22 +76,10 @@ void receiver(const std::string& ip, int port)
WireChunk* wireChunk = new WireChunk();
socketRead(&s, wireChunk, Chunk::getHeaderSize());
// cout << "WireChunk length: " << wireChunk->length << ", sec: " << wireChunk->tv_sec << ", usec: " << wireChunk->tv_usec << "\n";
wireChunk->payload = (char*)malloc(wireChunk->length);
socketRead(&s, wireChunk->payload, wireChunk->length);
/* void* wireChunk = (void*)malloc(sizeof(WireChunk));
size_t toRead = sizeof(WireChunk);
size_t len = 0;
do
{
len += s.read_some(boost::asio::buffer((char*)wireChunk + len, toRead));
toRead = sizeof(WireChunk) - len;
cout << "len: " << len << "\ttoRead: " << toRead << "\n";
}
while (toRead > 0);
*/
stream->addChunk(new Chunk(sampleRate, channels, bps, wireChunk));
stream->addChunk(new Chunk(format, wireChunk));
}
}
catch (const std::exception& e)
@ -113,58 +99,60 @@ void receiver(const std::string& ip, int port)
void player(Stream* stream)
{
unsigned int pcm, tmp, dir, rate;
int channels, seconds;
unsigned int pcm, tmp, rate;
int channels;
snd_pcm_t *pcm_handle;
snd_pcm_hw_params_t *params;
snd_pcm_uframes_t frames;
char *buff;
int buff_size;
rate = stream->getSampleRate();
channels = stream->getChannels();
rate = stream->format.rate;
channels = stream->format.channels;
/* Open the PCM device in playback mode */
if (pcm = snd_pcm_open(&pcm_handle, PCM_DEVICE,
SND_PCM_STREAM_PLAYBACK, 0) < 0)
printf("ERROR: Can't open \"%s\" PCM device. %s\n",
PCM_DEVICE, snd_strerror(pcm));
if ((pcm = snd_pcm_open(&pcm_handle, PCM_DEVICE, SND_PCM_STREAM_PLAYBACK, 0)) < 0)
cout << "ERROR: Can't open " << PCM_DEVICE << " PCM device. " << snd_strerror(pcm) << "\n";
/* struct snd_pcm_playback_info_t pinfo;
if ( (pcm = snd_pcm_playback_info( pcm_handle, &pinfo )) < 0 )
fprintf( stderr, "Error: playback info error: %s\n", snd_strerror( err ) );
printf("buffer: '%d'\n", pinfo.buffer_size);
*/
/* Allocate parameters object and fill it with default values*/
snd_pcm_hw_params_alloca(&params);
snd_pcm_hw_params_any(pcm_handle, params);
/* Set parameters */
if (pcm = snd_pcm_hw_params_set_access(pcm_handle, params,
SND_PCM_ACCESS_RW_INTERLEAVED) < 0)
printf("ERROR: Can't set interleaved mode. %s\n", snd_strerror(pcm));
if ((pcm = snd_pcm_hw_params_set_access(pcm_handle, params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
cout << "ERROR: Can't set interleaved mode. " << snd_strerror(pcm) << "\n";
if (pcm = snd_pcm_hw_params_set_format(pcm_handle, params,
SND_PCM_FORMAT_S16_LE) < 0)
printf("ERROR: Can't set format. %s\n", snd_strerror(pcm));
if ((pcm = snd_pcm_hw_params_set_format(pcm_handle, params, SND_PCM_FORMAT_S16_LE)) < 0)
cout << "ERROR: Can't set format. " << snd_strerror(pcm) << "\n";
if (pcm = snd_pcm_hw_params_set_channels(pcm_handle, params, channels) < 0)
printf("ERROR: Can't set channels number. %s\n", snd_strerror(pcm));
if ((pcm = snd_pcm_hw_params_set_channels(pcm_handle, params, channels)) < 0)
cout << "ERROR: Can't set channels number. " << snd_strerror(pcm) << "\n";
if (pcm = snd_pcm_hw_params_set_rate_near(pcm_handle, params, &rate, 0) < 0)
printf("ERROR: Can't set rate. %s\n", snd_strerror(pcm));
if ((pcm = snd_pcm_hw_params_set_rate_near(pcm_handle, params, &rate, 0)) < 0)
cout << "ERROR: Can't set rate. " << snd_strerror(pcm) << "\n";
long unsigned int periodsize = 2*rate / 50;
if (pcm = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, params, &periodsize) < 0)
printf("Unable to set buffer size %li: %s\n", (long int)periodsize, snd_strerror(pcm));
long unsigned int periodsize = 2*rate / 100;
if ((pcm = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, params, &periodsize)) < 0)
cout << "Unable to set buffer size " << (long int)periodsize << ": " << snd_strerror(pcm) << "\n";
/* Write parameters */
if (pcm = snd_pcm_hw_params(pcm_handle, params) < 0)
printf("ERROR: Can't set harware parameters. %s\n", snd_strerror(pcm));
if ((pcm = snd_pcm_hw_params(pcm_handle, params)) < 0)
cout << "ERROR: Can't set harware parameters. " << snd_strerror(pcm) << "\n";
/* Resume information */
printf("PCM name: '%s'\n", snd_pcm_name(pcm_handle));
cout << "PCM name: " << snd_pcm_name(pcm_handle) << "\n";
printf("PCM state: %s\n", snd_pcm_state_name(snd_pcm_state(pcm_handle)));
cout << "PCM state: " << snd_pcm_state_name(snd_pcm_state(pcm_handle)) << "\n";
snd_pcm_hw_params_get_channels(params, &tmp);
printf("channels: %i ", tmp);
cout << "channels: " << tmp << "\n";
if (tmp == 1)
printf("(mono)\n");
@ -172,19 +160,17 @@ void player(Stream* stream)
printf("(stereo)\n");
snd_pcm_hw_params_get_rate(params, &tmp, 0);
printf("rate: %d bps\n", tmp);
printf("seconds: %d\n", seconds);
cout << "rate: " << tmp << " bps\n";
/* Allocate buffer to hold single period */
snd_pcm_hw_params_get_period_size(params, &frames, 0);
printf("frames: %d\n", frames);
cout << "frames: " << frames << "\n";
buff_size = frames * channels * 2 /* 2 -> sample size */;
buff = (char *) malloc(buff_size);
snd_pcm_hw_params_get_period_time(params, &tmp, NULL);
printf("period time: %d\n", tmp);
cout << "period time: " << tmp << "\n";
while (true)
{
@ -197,9 +183,9 @@ void player(Stream* stream)
snd_pcm_sframes_t delay;
snd_pcm_avail_delay(pcm_handle, &avail, &delay);
stream->getPlayerChunk(buff, (float)delay / 48000.f, frames);
stream->getPlayerChunk(buff, (float)delay / stream->format.msRate(), frames);
if (pcm = snd_pcm_writei(pcm_handle, buff, frames) == -EPIPE) {
if ((pcm = snd_pcm_writei(pcm_handle, buff, frames)) == -EPIPE) {
printf("XRUN.\n");
snd_pcm_prepare(pcm_handle);
} else if (pcm < 0) {
@ -324,15 +310,14 @@ int main (int argc, char *argv[])
int bufferMs;
size_t port;
bool runAsDaemon;
string sampleFormat;
po::options_description desc("Allowed options");
desc.add_options()
("help,h", "produce help message")
("port,p", po::value<size_t>(&port)->default_value(98765), "port where the server listens on")
("ip,i", po::value<string>(&ip)->default_value("192.168.0.2"), "server IP")
("soundcard,s", po::value<int>(&deviceIdx)->default_value(-1), "index of the soundcard")
("channels,c", po::value<short>(&channels)->default_value(2), "number of channels")
("samplerate,r", po::value<uint16_t>(&sampleRate)->default_value(48000), "sample rate")
("bps", po::value<uint16_t>(&bps)->default_value(16), "bit per sample")
("sampleformat,f", po::value<string>(&sampleFormat)->default_value("48000:16:2"), "sample format")
("buffer,b", po::value<int>(&bufferMs)->default_value(300), "buffer size [ms]")
("daemon,d", po::bool_switch(&runAsDaemon)->default_value(false), "daemonize")
;
@ -354,35 +339,15 @@ int main (int argc, char *argv[])
std::clog << kLogNotice << "daemon started" << std::endl;
}
std::clog << kLogNotice << "test" << std::endl;
stream = new Stream(sampleRate, channels, bps);
stream = new Stream(SampleFormat(sampleFormat));
stream->setBufferLen(bufferMs);
// PaError paError;
// PaStream* paStream = initAudio(paError, sampleRate, channels, bps);
// stream->setLatency(1000*Pa_GetStreamInfo(paStream)->outputLatency);
std::thread receiverThread(receiver, ip, port);
std::thread receiverThread(receiver, stream->format, ip, port);
std::thread playerThread(player, stream);
std::string cmd;
while (true && (argc > 3))
{
std::cout << "> ";
std::getline(std::cin, cmd);
// line = fgets( str, 256, stdin );
// if (line == NULL)
// continue;
// std::string cmd(line);
std::cerr << "CMD: " << cmd << "\n";
if (cmd == "quit")
break;
else
{
stream->setBufferLen(atoi(cmd.c_str()));
}
}
playerThread.join();
return 0;

View file

@ -6,9 +6,8 @@
using namespace std;
Stream::Stream(size_t hz, size_t channels, size_t bps) : hz_(hz), channels_(channels), bytesPerSample_(bps/8), sleep(0), median(0), shortMedian(0), lastUpdate(0), latencyMs(0)
Stream::Stream(const SampleFormat& sampleFormat) : format(format_), format_(sampleFormat), sleep(0), median(0), shortMedian(0), lastUpdate(0)
{
frameSize_ = bytesPerSample_*channels_;
pBuffer = new DoubleBuffer<int>(1000);
pShortBuffer = new DoubleBuffer<int>(200);
pMiniBuffer = new DoubleBuffer<int>(20);
@ -47,16 +46,11 @@ time_point_ms Stream::getSilentPlayerChunk(void* outputBuffer, unsigned long fra
if (!chunk)
chunk = chunks.pop();
time_point_ms tp = chunk->timePoint();
memset(outputBuffer, 0, framesPerBuffer * frameSize_);
memset(outputBuffer, 0, framesPerBuffer * format.frameSize);
return tp;
}
void Stream::setLatency(size_t latency)
{
latencyMs = latency;
}
time_point_ms Stream::getNextPlayerChunk(void* outputBuffer, unsigned long framesPerBuffer, int correction)
{
@ -65,22 +59,22 @@ time_point_ms Stream::getNextPlayerChunk(void* outputBuffer, unsigned long frame
time_point_ms tp = chunk->timePoint();
int read = 0;
int toRead = framesPerBuffer + correction*(hz_/1000);
int toRead = framesPerBuffer + correction*format.msRate();
char* buffer;
if (correction != 0)
{
int msBuffer = floor(framesPerBuffer / (hz_/1000));
int msBuffer = floor(framesPerBuffer / format.msRate());
if (abs(correction) > msBuffer / 2)
correction = copysign(msBuffer / 2, correction);
buffer = (char*)malloc(toRead * frameSize_);
buffer = (char*)malloc(toRead * format.frameSize);
}
else
buffer = (char*)outputBuffer;
while (read < toRead)
{
read += chunk->read(buffer + read*frameSize_, toRead - read);
read += chunk->read(buffer + read*format.frameSize, toRead - read);
if (chunk->isEndOfChunk())
chunk = chunks.pop();
}
@ -93,7 +87,7 @@ time_point_ms Stream::getNextPlayerChunk(void* outputBuffer, unsigned long frame
for (size_t n=0; n<framesPerBuffer; ++n)
{
size_t index(floor(idx));// = (int)(ceil(n*factor));
memcpy((char*)outputBuffer + n*frameSize_, buffer + index*frameSize_, frameSize_);
memcpy((char*)outputBuffer + n*format.frameSize, buffer + index*format.frameSize, format.frameSize);
idx += factor;
}
free(buffer);
@ -122,13 +116,8 @@ void Stream::resetBuffers()
void Stream::getPlayerChunk(void* outputBuffer, double outputBufferDacTime, unsigned long framesPerBuffer)
{
if (outputBufferDacTime > 1)
outputBufferDacTime = 0;
else
outputBufferDacTime *= 1000;
//cout << "framesPerBuffer: " << framesPerBuffer << "\tms: " << framesPerBuffer*2 / PLAYER_CHUNK_MS_SIZE << "\t" << PLAYER_CHUNK_SIZE << "\n";
int msBuffer = framesPerBuffer / (hz_/1000);
//int msBuffer = framesPerBuffer / (format_.rate/1000);
//cout << msBuffer << " ms, " << framesPerBuffer << "\t" << hz_/1000 << "\n";
int ticks = 0;
long currentTick = getTickCount();
@ -149,7 +138,7 @@ int msBuffer = framesPerBuffer / (hz_/1000);
resetBuffers();
if (sleep < -10)
{
sleep = Chunk::getAge(getSilentPlayerChunk(outputBuffer, framesPerBuffer)) - bufferMs + latencyMs + outputBufferDacTime;
sleep = Chunk::getAge(getSilentPlayerChunk(outputBuffer, framesPerBuffer)) - bufferMs + outputBufferDacTime;
std::cerr << "Sleep: " << sleep << ", chunks: " << chunks.size() << "\n";
// std::clog << kLogNotice << "sleep: " << sleep << std::endl;
// if (sleep > -msBuffer/2)
@ -161,7 +150,7 @@ int msBuffer = framesPerBuffer / (hz_/1000);
// std::clog << kLogNotice << "sleep: " << sleep << std::endl;
while (true)
{
sleep = Chunk::getAge(getNextPlayerChunk(outputBuffer, framesPerBuffer)) - bufferMs + latencyMs + outputBufferDacTime;
sleep = Chunk::getAge(getNextPlayerChunk(outputBuffer, framesPerBuffer)) - bufferMs + outputBufferDacTime;
usleep(100);
// std::clog << kLogNotice << "age: " << age << std::endl;
if (sleep < 0)
@ -184,7 +173,7 @@ int msBuffer = framesPerBuffer / (hz_/1000);
int age = Chunk::getAge(getNextPlayerChunk(outputBuffer, framesPerBuffer, correction)) - bufferMs + latencyMs + outputBufferDacTime;// + outputBufferDacTime*1000;
int age = Chunk::getAge(getNextPlayerChunk(outputBuffer, framesPerBuffer, correction)) - bufferMs + outputBufferDacTime;
// if (pCardBuffer->full())

View file

@ -11,25 +11,18 @@
#include "common/chunk.h"
#include "common/timeUtils.h"
#include "common/queue.h"
#include "common/sampleFormat.h"
class Stream
{
public:
Stream(size_t hz, size_t channels, size_t bps);
Stream(const SampleFormat& format);
void addChunk(Chunk* chunk);
void clearChunks();
void getPlayerChunk(void* outputBuffer, double outputBufferDacTime, unsigned long framesPerBuffer);
void setBufferLen(size_t bufferLenMs);
void setLatency(size_t latency);
size_t getSampleRate() const
{
return hz_;
}
size_t getChannels() const
{
return channels_;
}
const SampleFormat& format;
private:
time_point_ms getNextPlayerChunk(void* outputBuffer, unsigned long framesPerBuffer, int correction = 0);
@ -37,15 +30,11 @@ private:
void updateBuffers(int age);
void resetBuffers();
size_t hz_;
size_t channels_;
size_t bytesPerSample_;
size_t frameSize_;
SampleFormat format_;
long lastTick;
int sleep;
// int correction;
Queue<std::shared_ptr<Chunk>> chunks;
DoubleBuffer<int>* pCardBuffer;
DoubleBuffer<int>* pMiniBuffer;
@ -57,7 +46,6 @@ private:
int shortMedian;
time_t lastUpdate;
int bufferMs;
int latencyMs;
};

View file

@ -1,19 +1,18 @@
#include "chunk.h"
#include <string.h>
#include <iostream>
#include "common/log.h"
Chunk::Chunk(size_t hz, size_t channels, size_t bitPerSample, WireChunk* _wireChunk) : wireChunk(_wireChunk), hz_(hz), channels_(channels), bytesPerSample_(bitPerSample/8), idx(0)
Chunk::Chunk(const SampleFormat& sampleFormat, WireChunk* _wireChunk) : wireChunk(_wireChunk), format(format_), format_(sampleFormat), idx(0)
{
frameSize_ = bytesPerSample_*channels_;
}
Chunk::Chunk(size_t hz, size_t channels, size_t bitPerSample, size_t ms) : hz_(hz), channels_(channels), bytesPerSample_(bitPerSample/8), idx(0)
Chunk::Chunk(const SampleFormat& sampleFormat, size_t ms) : format(format_), format_(sampleFormat), idx(0)
{
frameSize_ = bytesPerSample_*channels_;
wireChunk = new WireChunk;
wireChunk->length = hz*frameSize_*ms / 1000;
wireChunk->length = format.rate*format.frameSize*ms / 1000;
wireChunk->payload = (char*)malloc(wireChunk->length);
}
@ -27,32 +26,31 @@ Chunk::~Chunk()
bool Chunk::isEndOfChunk() const
{
return idx >= (wireChunk->length / frameSize_);
return idx >= (wireChunk->length / format.frameSize);
}
double Chunk::getDuration() const
{
// std::cout << "len: " << wireChunk->length << ", channels: " << channels_ << ", bytesPerSample: " << bytesPerSample_ << ", hz: " << hz_ << "\n";
return wireChunk->length / (frameSize_ * hz_ / 1000.);
return (wireChunk->length / format.frameSize) / ((double)format.rate / 1000.);
}
int Chunk::read(void* outputBuffer, size_t frameCount)
{
//std::cout << "read: " << frameCount << ", total: " << (wireChunk->length / frameSize_) << ", idx: " << idx;// << std::endl;
//logd << "read: " << frameCount << ", total: " << (wireChunk->length / format.frameSize) << ", idx: " << idx;// << std::endl;
int result = frameCount;
if (idx + frameCount > (wireChunk->length / frameSize_))
result = (wireChunk->length / frameSize_) - idx;
if (idx + frameCount > (wireChunk->length / format.frameSize))
result = (wireChunk->length / format.frameSize) - idx;
//std::cout << ", from: " << frameSize_*idx << ", to: " << frameSize_*idx + frameSize_*result;
//logd << ", from: " << format.frameSize*idx << ", to: " << format.frameSize*idx + format.frameSize*result;
if (outputBuffer != NULL)
memcpy((char*)outputBuffer, (char*)(wireChunk->payload) + frameSize_*idx, frameSize_*result);
memcpy((char*)outputBuffer, (char*)(wireChunk->payload) + format.frameSize*idx, format.frameSize*result);
idx += result;
//std::cout << ", new idx: " << idx << ", result: " << result << std::endl;
//logd << ", new idx: " << idx << ", result: " << result << ", wireChunk->length: " << wireChunk->length << ", format.frameSize: " << format.frameSize << "\n";//std::endl;
return result;
}

View file

@ -3,7 +3,7 @@
#include <chrono>
#include <cstdlib>
#include "common/sampleFormat.h"
typedef std::chrono::time_point<std::chrono::high_resolution_clock, std::chrono::milliseconds> time_point_ms;
@ -22,19 +22,11 @@ struct WireChunk
class Chunk
{
public:
Chunk(size_t hz, size_t channels, size_t bitPerSample, WireChunk* _wireChunk);
Chunk(size_t hz, size_t channels, size_t bitPerSample, size_t ms);
Chunk(const SampleFormat& sampleFormat, WireChunk* _wireChunk);
Chunk(const SampleFormat& sampleFormat, size_t ms);
~Chunk();
/* static WireChunk* make_chunk(size_t size, size_t bytesPerSample)
{
WireChunk* wireChunk = new WireChunk(bytesPerSample*size);
wireChunk->length = bytesPerSample*size;
wireChunk->payload = (char*)malloc(wireChunk->length);
return wireChunk;
}
*/
static size_t getHeaderSize()
static inline size_t getHeaderSize()
{
return sizeof(WireChunk::tv_sec) + sizeof(WireChunk::tv_usec) + sizeof(WireChunk::length);
}
@ -45,7 +37,12 @@ public:
inline time_point_ms timePoint() const
{
time_point_ms tp;
return tp + std::chrono::seconds(wireChunk->tv_sec) + std::chrono::milliseconds(wireChunk->tv_usec / 1000) + std::chrono::milliseconds(idx / (hz_/1000));
std::chrono::milliseconds::rep relativeIdxTp = ((double)idx / ((double)format.rate/1000.));
return
tp +
std::chrono::seconds(wireChunk->tv_sec) +
std::chrono::milliseconds(wireChunk->tv_usec / 1000) +
std::chrono::milliseconds(relativeIdxTp);
}
template<typename T>
@ -73,14 +70,11 @@ public:
double getDuration() const;
WireChunk* wireChunk;
size_t hz_;
size_t channels_;
size_t bytesPerSample_;
size_t frameSize_;
const SampleFormat& format;
private:
int32_t idx;
SampleFormat format_;
uint32_t idx;
};

View file

@ -11,7 +11,10 @@ Log::Log(std::string ident, int facility) {
int Log::sync() {
if (buffer_.length()) {
syslog(priority_, buffer_.c_str());
if (priority_ == dbg)
std::cout << buffer_.c_str();
else
syslog(priority_, "%s", buffer_.c_str());
buffer_.erase();
priority_ = LOG_DEBUG; // default to debug for each message
}
@ -29,6 +32,8 @@ int Log::overflow(int c) {
std::ostream& operator<< (std::ostream& os, const LogPriority& log_priority) {
static_cast<Log *>(os.rdbuf())->priority_ = (int)log_priority;
if (log_priority == dbg)
os.flush();
return os;
}

View file

@ -5,6 +5,7 @@
#include <iostream>
#include <cstring>
#define logd std::clog << dbg
enum LogPriority {
kLogEmerg = LOG_EMERG, // system is unusable
@ -14,7 +15,8 @@ enum LogPriority {
kLogWarning = LOG_WARNING, // warning conditions
kLogNotice = LOG_NOTICE, // normal, but significant, condition
kLogInfo = LOG_INFO, // informational message
kLogDebug = LOG_DEBUG // debug-level message
kLogDebug = LOG_DEBUG, // debug-level message
dbg
};
std::ostream& operator<< (std::ostream& os, const LogPriority& log_priority);

44
common/sampleFormat.cpp Normal file
View file

@ -0,0 +1,44 @@
#include "sampleFormat.h"
#include <vector>
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
#include <iostream>
SampleFormat::SampleFormat(const std::string& format) : rate(rate_), bits(bits_), channels(channels_), sampleSize(bytes_), frameSize(frameSize_)
{
setFormat(format);
}
SampleFormat::SampleFormat(uint16_t sampleRate, uint16_t bitsPerSample, uint16_t channelCount) : rate(rate_), bits(bits_), channels(channels_), sampleSize(bytes_), frameSize(frameSize_)
{
setFormat(sampleRate, bitsPerSample, channelCount);
}
void SampleFormat::setFormat(const std::string& format)
{
std::vector<std::string> strs;
boost::split(strs, format, boost::is_any_of(":"));
if (strs.size() == 3)
setFormat(
boost::lexical_cast<uint16_t>(strs[0]),
boost::lexical_cast<uint16_t>(strs[1]),
boost::lexical_cast<uint16_t>(strs[2]));
}
void SampleFormat::setFormat(uint16_t rate, uint16_t bits, uint16_t channels)
{
rate_ = rate;
bits_ = bits;
bytes_ = bits / 8;
channels_ = channels;
if (bits_ == 24)
bytes_ = 4;
frameSize_ = channels_*bytes_;
}

36
common/sampleFormat.h Normal file
View file

@ -0,0 +1,36 @@
#ifndef SAMPLE_FORMAT
#define SAMPLE_FORMAT
#include <string>
class SampleFormat
{
public:
SampleFormat();
SampleFormat(const std::string& format);
SampleFormat(uint16_t rate = 48000, uint16_t bits = 16, uint16_t channels = 2);
void setFormat(const std::string& format);
void setFormat(uint16_t rate, uint16_t bits, uint16_t channels);
const uint16_t& rate;
const uint16_t& bits;
const uint16_t& channels;
const uint16_t& sampleSize;
const uint16_t& frameSize;
float msRate() const { return (float)rate/1000.f; }
private:
uint16_t rate_;
uint16_t bits_;
uint16_t channels_;
uint16_t bytes_;
uint16_t frameSize_;
};
#endif

BIN
common/sampleFormat.o Normal file

Binary file not shown.

View file

@ -3,7 +3,7 @@ CC = /usr/bin/g++
CFLAGS = -std=gnu++0x -Wall -Wno-unused-function -D_REENTRANT -DVERSION=\"$(VERSION)\" -I..
LDFLAGS = -lrt -lpthread -lportaudio -lboost_system -lboost_program_options
OBJ = snapServer.o ../common/chunk.o
OBJ = snapServer.o ../common/chunk.o ../common/sampleFormat.o
BIN = snapserver
all: server

View file

@ -25,6 +25,7 @@
#include "common/queue.h"
#include "common/signalHandler.h"
#include "common/utils.h"
#include "common/sampleFormat.h"
#include <syslog.h>
@ -201,9 +202,7 @@ int main(int argc, char* argv[])
{
try
{
uint16_t sampleRate;
short channels;
uint16_t bps;
string sampleFormat;
size_t port;
string fifoName;
@ -213,9 +212,7 @@ int main(int argc, char* argv[])
desc.add_options()
("help,h", "produce help message")
("port,p", po::value<size_t>(&port)->default_value(98765), "port to listen on")
("channels,c", po::value<short>(&channels)->default_value(2), "number of channels")
("samplerate,r", po::value<uint16_t>(&sampleRate)->default_value(48000), "sample rate")
("bps,b", po::value<uint16_t>(&bps)->default_value(16), "bit per sample")
("sampleformat,f", po::value<string>(&sampleFormat)->default_value("48000:16:2"), "sample format")
("fifo,f", po::value<string>(&fifoName)->default_value("/tmp/snapfifo"), "name of fifo file")
("daemon,d", po::bool_switch(&runAsDaemon)->default_value(false), "daemonize")
;
@ -264,6 +261,7 @@ int main(int argc, char* argv[])
mkfifo(fifoName.c_str(), 0777);
size_t duration = 50;
SampleFormat format(sampleFormat);
while (!g_terminated)
{
int fd = open(fifoName.c_str(), O_RDONLY);
@ -272,7 +270,7 @@ size_t duration = 50;
shared_ptr<Chunk> chunk;//(new WireChunk());
while (true)//cin.good())
{
chunk.reset(new Chunk(sampleRate, channels, bps, duration));//2*WIRE_CHUNK_SIZE));
chunk.reset(new Chunk(format, duration));//2*WIRE_CHUNK_SIZE));
WireChunk* wireChunk = chunk->wireChunk;
int toRead = wireChunk->length;
// cout << "tr: " << toRead << ", size: " << WIRE_CHUNK_SIZE << "\t";