read from stdin

pull/7/head
Marcin Kondej 2015-07-28 15:47:53 +02:00
rodzic bc0b0d4a33
commit e47723a788
13 zmienionych plików z 229 dodań i 69 usunięć

Wyświetl plik

@ -8,6 +8,7 @@
Redistribution and use in source and binary forms, with or without modification, are
permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.

Wyświetl plik

@ -8,6 +8,7 @@
Redistribution and use in source and binary forms, with or without modification, are
permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.

Wyświetl plik

@ -8,6 +8,7 @@
Redistribution and use in source and binary forms, with or without modification, are
permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.

Wyświetl plik

@ -43,6 +43,8 @@
<Unit filename="error_reporter.h" />
<Unit filename="main.cpp" />
<Unit filename="pcm_wave_header.h" />
<Unit filename="stdin_reader.cpp" />
<Unit filename="stdin_reader.h" />
<Unit filename="transmitter.cpp" />
<Unit filename="transmitter.h" />
<Unit filename="wave_reader.cpp" />

Wyświetl plik

@ -52,31 +52,33 @@
1437597555 /home/pi/Projects/fm_transmitter/error_reporter.h
<string>
1435357888 source:/home/marcin/Repozytoria/fm_transmitter/error_reporter.cpp
1438083081 source:/home/marcin/Repozytoria/fm_transmitter/error_reporter.cpp
"error_reporter.h"
1435358040 /home/marcin/Repozytoria/fm_transmitter/error_reporter.h
1438083081 /home/marcin/Repozytoria/fm_transmitter/error_reporter.h
<string>
1436380561 source:/home/marcin/Repozytoria/fm_transmitter/main.cpp
1438083081 source:/home/marcin/Repozytoria/fm_transmitter/main.cpp
<iostream>
"transmitter.h"
<cstdlib>
1436384608 /home/marcin/Repozytoria/fm_transmitter/transmitter.h
1438084671 /home/marcin/Repozytoria/fm_transmitter/transmitter.h
"wave_reader.h"
"audio_format.h"
"stdin_reader.h"
"error_reporter.h"
1436380561 /home/marcin/Repozytoria/fm_transmitter/wave_reader.h
1438090504 /home/marcin/Repozytoria/fm_transmitter/wave_reader.h
<string>
<vector>
<fstream>
"error_reporter.h"
"audio_format.h"
"pcm_wave_header.h"
"error_reporter.h"
1435355417 /home/marcin/Repozytoria/fm_transmitter/pcm_wave_header.h
1438083081 /home/marcin/Repozytoria/fm_transmitter/pcm_wave_header.h
1436384617 source:/home/marcin/Repozytoria/fm_transmitter/transmitter.cpp
1438084940 source:/home/marcin/Repozytoria/fm_transmitter/transmitter.cpp
"transmitter.h"
<exception>
<sstream>
@ -85,11 +87,10 @@
<unistd.h>
<sys/mman.h>
<fcntl.h>
<pthread.h>
1435675612 /home/marcin/Repozytoria/fm_transmitter/audio_format.h
1438083081 /home/marcin/Repozytoria/fm_transmitter/audio_format.h
1436380561 source:/home/marcin/Repozytoria/fm_transmitter/wave_reader.cpp
1438090504 source:/home/marcin/Repozytoria/fm_transmitter/wave_reader.cpp
"wave_reader.h"
<exception>
<sstream>
@ -236,3 +237,15 @@
1437741006 source:/home/pi/new_transmitter/stdin_reader.cpp
"stdin_reader.h"
1438091088 /home/marcin/Repozytoria/fm_transmitter/stdin_reader.h
<vector>
<fcntl.h>
"audio_format.h"
"error_reporter.h"
1438085397 source:/home/marcin/Repozytoria/fm_transmitter/stdin_reader.cpp
"stdin_reader.h"
<exception>
<sstream>
<unistd.h>

Wyświetl plik

@ -8,6 +8,7 @@
Redistribution and use in source and binary forms, with or without modification, are
permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
@ -51,11 +52,11 @@ int main(int argc, char **argv)
try {
transmitter = new Transmitter(filename, frequency);
AudioFormat *format = transmitter->getFormat();
AudioFormat format = transmitter->getFormat();
cout << "Playing: " << filename << ", "
<< format->sampleRate << " Hz, "
<< format->bitsPerSample << " bits, "
<< ((format->channels > 0x01) ? "stereo" : "mono") << endl;
<< format.sampleRate << " Hz, "
<< format.bitsPerSample << " bits, "
<< ((format.channels > 0x01) ? "stereo" : "mono") << endl;
transmitter->play();
} catch (exception &e) {

Wyświetl plik

@ -8,6 +8,7 @@
Redistribution and use in source and binary forms, with or without modification, are
permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.

Wyświetl plik

@ -1,22 +1,124 @@
/*
fm_transmitter - use Raspberry Pi as FM transmitter
Copyright (c) 2015, Marcin Kondej
All rights reserved.
See https://github.com/markondej/fm_transmitter
Redistribution and use in source and binary forms, with or without modification, are
permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be
used to endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "stdin_reader.h"
#include <exception>
#include <sstream>
#include <unistd.h>
using std::exception;
using std::ostringstream;
StdinReader::StdinReader()
{
//ctor
}
StdinReader::~StdinReader()
{
//dtor
{
ostringstream oss;
doStop = false;
int returnCode = pthread_create(&thread, NULL, (volatile void*)(&this->readStdin), NULL);
if (returnCode) {
oss << "Cannot create new thread (code: " << returnCode << ")";
errorMessage = oss.str();
throw exception();
}
}
vector<float> *StdinReader::getFrames(unsigned int count)
StdinReader::~StdinReader()
{
return new vector<float>();
doStop = true;
pthread_join(thread, NULL);
}
StdinReader *StdinReader::getInstance()
{
static StdinReader instance;
return &instance;
}
void StdinReader::readStdin()
{
char *readBuffer = new char[BUFFER_SIZE];
while(!doStop) {
int bytes = read(STDIN_FILENO, readBuffer, BUFFER_SIZE);
buffer.insert(buffer.end(), readBuffer, readBuffer + bytes);
usleep(1);
}
}
vector<float> *StdinReader::getFrames(unsigned int frameCount)
{
unsigned int bytesToRead, bufferSize, bytesPerFrame, offset, zeroOffset, restBytes;
vector<float> *frames = new vector<float>();
bufferSize = buffer.size();
bytesPerFrame = (BITS_PER_SAMPLE >> 3) * CHANNELS;
bytesToRead = frameCount * bytesPerFrame;
restBytes = bufferSize % bytesPerFrame;
if (bytesToRead > bufferSize) {
bytesToRead = bufferSize - restBytes;
frameCount = bytesToRead / bytesPerFrame;
}
zeroOffset = bufferSize - bytesToRead - restBytes;
for (unsigned int i = 0; i < frameCount; i++) {
offset = zeroOffset + bytesPerFrame * i;
if (CHANNELS != 1) {
if (BITS_PER_SAMPLE != 8) {
frames->push_back(((int)(signed char)buffer[offset + 1] + (int)(signed char)buffer[offset + 3]) / (float)0x100);
} else {
frames->push_back(((int)buffer[offset] + (int)buffer[offset + 1]) / (float)0x100 - 1.0f);
}
} else {
if (BITS_PER_SAMPLE != 8) {
frames->push_back((signed char)buffer[offset + 1] / (float)0x80);
} else {
frames->push_back(buffer[offset] / (float)0x80 - 1.0f);
}
}
}
buffer.clear();
return frames;
}
AudioFormat *StdinReader::getFormat()
{
AudioFormat *format = new AudioFormat;
format->sampleRate = SAMPLE_RATE;
format->bitsPerSample = BITS_PER_SAMPLE;
format->channels = CHANNELS;
return format;
}

Wyświetl plik

@ -1,19 +1,66 @@
/*
fm_transmitter - use Raspberry Pi as FM transmitter
Copyright (c) 2015, Marcin Kondej
All rights reserved.
See https://github.com/markondej/fm_transmitter
Redistribution and use in source and binary forms, with or without modification, are
permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be
used to endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef STDIN_READER_H
#define STDIN_READER_H
#include <vector>
#include <fcntl.h>
#include "audio_format.h"
#include "error_reporter.h"
#define BUFFER_SIZE 128
#define SAMPLE_RATE 22500
#define BITS_PER_SAMPLE 1
#define CHANNELS 1
using std::vector;
class StdinReader
class StdinReader : public ErrorReporter
{
public:
StdinReader();
virtual ~StdinReader();
vector<float> *getFrames(unsigned int count);
pthread_t thread;
static StdinReader *getInstance();
vector<float> *getFrames(unsigned int frameCount);
AudioFormat *getFormat();
private:
StdinReader();
bool doStop;
void readStdin();
vector<char> buffer;
};
#endif // STDIN_READER_H

Wyświetl plik

@ -8,6 +8,7 @@
Redistribution and use in source and binary forms, with or without modification, are
permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
@ -46,8 +47,6 @@ using std::ostringstream;
#define ACCESS64(base, offset) *(volatile unsigned long long*)((int)base + offset)
bool Transmitter::isTransmitting = false;
vector<float> *Transmitter::buffer = NULL;
unsigned int Transmitter::frameOffset = 0;
Transmitter::Transmitter(string filename, double frequency) :
readStdin(filename == "-")
@ -88,16 +87,15 @@ Transmitter::Transmitter(string filename, double frequency) :
peripherals = (volatile unsigned*)peripheralsMap;
AudioFormat *audioFormat;
if (!readStdin) {
waveReader = new WaveReader(filename);
format = waveReader->getFormat();
audioFormat = waveReader->getFormat();
} else {
stdinReader = new StdinReader();
format = stdinReader->getFormat();
stdinReader = StdinReader::getInstance();
audioFormat = stdinReader->getFormat();
}
ACCESS(peripherals, 0x00200000) = (ACCESS(peripherals, 0x00200000) & 0xFFFF8FFF) | (0x01 << 14);
ACCESS(peripherals, 0x00101070) = (0x5A << 24) | (0x01 << 9) | (0x01 << 4) | 0x06;
format = *audioFormat;
clockDivisor = (unsigned int)((500 << 12) / frequency + 0.5);
}
@ -112,22 +110,15 @@ void Transmitter::play()
throw exception();
}
frameOffset = 0;
isTransmitting = true;
pthread_t thread;
int returnCode;
frameOffset = 0;
unsigned int bufferFrames = (unsigned int)((unsigned long long)format->sampleRate * BUFFER_TIME / 1000000);
unsigned int bufferFrames = (unsigned int)((unsigned long long)format.sampleRate * BUFFER_TIME / 1000000);
buffer = (!readStdin) ? waveReader->getFrames(bufferFrames, frameOffset) : stdinReader->getFrames(bufferFrames);
void *params[3];
params[0] = &format->sampleRate;
params[1] = &clockDivisor;
params[2] = peripherals;
returnCode = pthread_create(&thread, NULL, &Transmitter::transmit, (void*)params);
int returnCode = pthread_create(&thread, NULL, (volatile void*)(&this->transmit), NULL);
if (returnCode) {
oss << "Cannot create new thread (code: " << returnCode << ")";
errorMessage = oss.str();
@ -147,16 +138,15 @@ void Transmitter::play()
pthread_join(thread, NULL);
}
void Transmitter::transmit(void *params)
void Transmitter::transmit(void*)
{
unsigned long long current, start, playbackStart;
unsigned int offset = 0, length, temp;
vector<float> *frames;
float *data;
unsigned int sampleRate = *((unsigned int**)params)[0];
unsigned int clockDivisor = *((unsigned int**)params)[1];
volatile unsigned *peripherals = ((unsigned int**)params)[2];
ACCESS(peripherals, 0x00200000) = (ACCESS(peripherals, 0x00200000) & 0xFFFF8FFF) | (0x01 << 14);
ACCESS(peripherals, 0x00101070) = (0x5A << 24) | (0x01 << 9) | (0x01 << 4) | 0x06;
playbackStart = ACCESS64(peripherals, 0x00003004);
current = playbackStart;
@ -168,7 +158,7 @@ void Transmitter::transmit(void *params)
current = ACCESS64(peripherals, 0x00003004);
}
frames = buffer;
frameOffset = (current - playbackStart) * sampleRate / 1000000;
frameOffset = (current - playbackStart) * format.sampleRate / 1000000;
buffer = NULL;
length = frames->size();
@ -189,7 +179,7 @@ void Transmitter::transmit(void *params)
usleep(1);
current = ACCESS64(peripherals, 0x00003004);
offset = (current - start) * sampleRate / 1000000;
offset = (current - start) * format.sampleRate / 1000000;
}
}
@ -197,21 +187,21 @@ void Transmitter::transmit(void *params)
delete frames;
}
ACCESS(peripherals, 0x00101070) = (0x5A << 24);
}
Transmitter::~Transmitter()
{
ACCESS(peripherals, 0x00101070) = (0x5A << 24);
munmap(peripherals, 0x002FFFFF);
if (!readStdin) {
delete waveReader;
} else {
delete stdinReader;
}
delete format;
}
AudioFormat *Transmitter::getFormat()
AudioFormat& Transmitter::getFormat()
{
return format;
}

Wyświetl plik

@ -8,6 +8,7 @@
Redistribution and use in source and binary forms, with or without modification, are
permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
@ -35,6 +36,7 @@
#include "wave_reader.h"
#include "stdin_reader.h"
#include "error_reporter.h"
#define BUFFER_TIME 1000000
@ -46,21 +48,21 @@ class Transmitter : public ErrorReporter
Transmitter(string filename, double frequency);
virtual ~Transmitter();
AudioFormat *getFormat();
AudioFormat &getFormat();
void play();
private:
bool readStdin;
AudioFormat *format;
AudioFormat format;
WaveReader *waveReader;
StdinReader *stdinReader;
unsigned int clockDivisor;
volatile unsigned *peripherals;
static vector<float> *buffer;
vector<float> *buffer;
unsigned int frameOffset;
static bool isTransmitting;
static unsigned int frameOffset;
static void transmit(void *params);
void transmit(void*);
};
#endif // TRANSMITTER_H

Wyświetl plik

@ -8,6 +8,7 @@
Redistribution and use in source and binary forms, with or without modification, are
permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
@ -35,8 +36,6 @@
#include <sstream>
#include <string.h>
#include <iostream>
using std::exception;
using std::ostringstream;
@ -142,12 +141,11 @@ vector<char> *WaveReader::readData(unsigned int bytesToRead, bool closeFileOnExc
return data;
}
vector<float> *WaveReader::getFrames(unsigned int count, unsigned int frameOffset) {
unsigned int bytesToRead, bytesLeft, bytesPerFrame, frameCount, offset;
vector<float> *WaveReader::getFrames(unsigned int frameCount, unsigned int frameOffset) {
unsigned int bytesToRead, bytesLeft, bytesPerFrame, offset;
vector<float> *frames = new vector<float>();
vector<char> *data;
frameCount = count;
bytesPerFrame = (header.bitsPerSample >> 3) * header.channels;
bytesToRead = frameCount * bytesPerFrame;
bytesLeft = header.subchunk2Size - frameOffset * bytesPerFrame;

Wyświetl plik

@ -8,6 +8,7 @@
Redistribution and use in source and binary forms, with or without modification, are
permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
@ -36,9 +37,9 @@
#include <string>
#include <vector>
#include <fstream>
#include "error_reporter.h"
#include "pcm_wave_header.h"
#include "audio_format.h"
#include "pcm_wave_header.h"
#include "error_reporter.h"
using std::vector;
using std::string;
@ -51,7 +52,7 @@ class WaveReader : public ErrorReporter
virtual ~WaveReader();
AudioFormat *getFormat();
vector<float> *getFrames(unsigned int count, unsigned int offset);
vector<float> *getFrames(unsigned int frameCount, unsigned int frameOffset);
bool isEnd();
private:
string filename;