Get broadcasting of already formatted files working

pull/13/head
Brandon Skari 2016-01-19 03:05:45 +07:00
rodzic 1aef5f7c5d
commit 4634b2ffd2
3 zmienionych plików z 106 dodań i 67 usunięć

Wyświetl plik

@ -23,5 +23,5 @@ setup(
),
],
package_dir={'': 'src/python'},
install_requires=['pydub'],
install_requires=['pydub', 'wave'],
)

Wyświetl plik

@ -15,95 +15,123 @@ static SNDFILE* sndFile;
// These methods used by libsndfile's virtual file open function
sf_count_t virtualSndfileGetLength(void* unused) {
return sampleLength;
static sf_count_t virtualSndfileGetLength(void* unused) {
return sampleLength;
}
sf_count_t virtualSndfileRead(void* const dest, const sf_count_t count, void* const userData) {
const sf_count_t bytesAvailable = sampleLength - sampleOffset;
const int numBytes = bytesAvailable > count ? count : bytesAvailable;
memcpy(dest, userData, numBytes);
sampleOffset += numBytes;
return numBytes;
static sf_count_t virtualSndfileRead(void* const dest, const sf_count_t count, void* const userData) {
const sf_count_t bytesAvailable = sampleLength - sampleOffset;
const int numBytes = bytesAvailable > count ? count : bytesAvailable;
memcpy(dest, ((char*)userData) + sampleOffset, numBytes);
sampleOffset += numBytes;
return numBytes;
}
static sf_count_t virtualSndfileTell(void* const unused) {
return sampleOffset;
}
static sf_count_t virtualSndfileSeek(const sf_count_t offset, const int whence, void* const unused) {
switch (whence) {
case SEEK_CUR:
sampleOffset += offset;
break;
case SEEK_SET:
sampleOffset = offset;
break;
case SEEK_END:
sampleOffset = sampleLength - offset;
break;
default:
assert(!"Invalid whence");
}
return sampleOffset;
}
static sf_count_t virtualSndfileWrite(const void *ptr, sf_count_t count, void *user_data) {
return 0;
}
typedef struct {
double frequency;
uint32_t waitForThisSample;
double frequency;
uint32_t waitForThisSample;
} samplerf_t;
/**
* Formats a chunk of an array of a mono 44k wav at a time and outputs IQ
* formatted array for broadcast.
*/
ssize_t formatIqWrapper(void* const outBuffer, size_t count) {
static float readBuffer[1024];
const int excursion = 6000;
samplerf_t samplerf;
char* out = outBuffer;
static ssize_t formatRfWrapper(void* const outBuffer, const size_t count) {
static float wavBuffer[1024];
static int wavOffset = 0;
static int wavFilled = 0;
int readCount;
int k;
int totalBytesToRead = count / sizeof(samplerf_t);
int bytesToRead = totalBytesToRead;
if (bytesToRead > COUNT_OF(readBuffer)) {
bytesToRead = COUNT_OF(readBuffer);
}
int bytesWritten = 0;
while ((readCount = sf_readf_float(sndFile, readBuffer, bytesToRead))) {
for (k = 0; k < readCount; k++) {
const int x = readBuffer[k];
samplerf.frequency = x * excursion * 2.0;
samplerf.waitForThisSample = 1e9 / 48000.0; //en 100 de nanosecond
memcpy(&out[bytesWritten], &samplerf, sizeof(samplerf_t));
bytesWritten += sizeof(samplerf_t);
}
totalBytesToRead -= bytesToRead;
if (totalBytesToRead <= 0) {
break;
}
}
return bytesWritten;
const int excursion = 6000;
int numBytesWritten = 0;
samplerf_t samplerf;
char* const out = outBuffer;
while (numBytesWritten < count) {
for (; numBytesWritten <= count - sizeof(samplerf_t) && wavOffset < wavFilled; ++wavOffset) {
const float x = wavBuffer[wavOffset];
samplerf.frequency = x * excursion * 2.0;
samplerf.waitForThisSample = 1e9 / 48000.0; //en 100 de nanosecond
memcpy(&out[numBytesWritten], &samplerf, sizeof(samplerf_t));
numBytesWritten += sizeof(samplerf_t);
}
assert(wavOffset <= wavFilled);
if (wavOffset == wavFilled) {
wavFilled = sf_readf_float(sndFile, wavBuffer, COUNT_OF(wavBuffer));
wavOffset = 0;
}
}
return numBytesWritten;
}
static void reset(void) {
sampleOffset = 0;
}
static PyObject*
_rpitx_broadcast_fm(PyObject* self, PyObject* args) {
int address;
int length;
float frequency;
if (!PyArg_ParseTuple(args, "iif", &address, &length, &frequency)) {
return NULL;
}
int address;
int length;
float frequency;
if (!PyArg_ParseTuple(args, "iif", &address, &length, &frequency)) {
return NULL;
}
sampleBase = (void*)address;
sampleLength = length;
sampleOffset = 0;
sampleBase = (void*)address;
sampleLength = length;
sampleOffset = 0;
SF_VIRTUAL_IO virtualIo = {
.get_filelen = virtualSndfileGetLength,
.seek = NULL,
.read = virtualSndfileRead,
.write = NULL,
.tell = NULL
};
SF_INFO sfInfo ;
sndFile = sf_open_virtual(&virtualIo, SFM_READ, &sfInfo, sampleBase);
SF_VIRTUAL_IO virtualIo = {
.get_filelen = virtualSndfileGetLength,
.seek = virtualSndfileSeek,
.read = virtualSndfileRead,
.write = virtualSndfileWrite,
.tell = virtualSndfileTell
};
SF_INFO sfInfo;
sndFile = sf_open_virtual(&virtualIo, SFM_READ, &sfInfo, sampleBase);
if (sf_error(sndFile) != SF_ERR_NO_ERROR) {
// TODO: Throw an exception
fprintf(stderr, "Unable to open sound file: %s\n", sf_strerror(sndFile));
Py_RETURN_NONE;
}
pitx_run(MODE_IQ, 44000, frequency, 0.0, 0, formatIqWrapper, NULL);
sf_close(sndFile);
pitx_run(MODE_RF, 48000, frequency * 1000.0, 0.0, 0, formatRfWrapper, reset);
sf_close(sndFile);
Py_RETURN_NONE;
Py_RETURN_NONE;
}
static PyMethodDef _rpitx_methods[] = {
{"broadcast_fm", _rpitx_broadcast_fm, METH_VARARGS, "Low-level broadcasting."},
{NULL, NULL, 0, NULL}
{"broadcast_fm", _rpitx_broadcast_fm, METH_VARARGS, "Low-level broadcasting."},
{NULL, NULL, 0, NULL}
};
PyMODINIT_FUNC
init_rpitx(void) {
(void) Py_InitModule("_rpitx", _rpitx_methods);
(void) Py_InitModule("_rpitx", _rpitx_methods);
}

Wyświetl plik

@ -6,6 +6,7 @@ import _rpitx
import array
import logging
import os
import wave
def broadcast_fm(file_, frequency):
@ -32,13 +33,23 @@ def broadcast_fm(file_, frequency):
):
logger.debug('Reencoding file')
reencoded = StringIO.StringIO()
original.export(reencoded, format='wav', bitrate='44k')
return reencoded
return AudioSegment.from_file(reencoded)
return original
encoded_file = _reencode(file_)
raw_audio_data = _reencode(file_)
wav_data = StringIO.StringIO()
wav_writer = wave.open(wav_data, 'w')
wav_writer.setnchannels(1)
wav_writer.setsampwidth(2)
wav_writer.setframerate(48000)
wav_writer.writeframes(raw_audio_data.raw_data)
wav_writer.close()
raw_array = array.array('c')
raw_array.fromstring(encoded_file.raw_data)
raw_array.fromstring(wav_data.getvalue())
#with open('sampleaudio.wav', 'rb') as file_:
# raw_array.fromstring(file_.read())
array_address, length = raw_array.buffer_info()
_rpitx.broadcast_fm(array_address, length, frequency)