Ogg source (#70)

* Start Ogg source block

* Add OGG audio source block

The number of output streams for this block should match the number of
audio streams contained inside the ogg file. If there is a mismatch an
appropriate exception is thrown.
This commit is contained in:
Manolis Surligas 2017-04-01 16:21:15 +03:00 committed by GitHub
parent c83e53f9b5
commit 165423d64c
9 changed files with 276 additions and 3 deletions

View File

@ -49,5 +49,5 @@ if(${INCLUDE_DEBUG_BLOCKS})
endif()
install(FILES
${enabled_blocks}
DESTINATION share/gnuradio/grc/blocks
satnogs_ogg_source.xml DESTINATION share/gnuradio/grc/blocks
)

View File

@ -14,6 +14,7 @@
<block>satnogs_morse_decoder</block>
<block>satnogs_multi_format_msg_sink</block>
<block>satnogs_ogg_encoder</block>
<block>satnogs_ogg_source</block>
<block>satnogs_cw_to_symbol</block>
<block>satnogs_sine_matched_filter_ff</block>
<block>satnogs_udp_msg_source</block>

View File

@ -0,0 +1,28 @@
<?xml version="1.0"?>
<block>
<name>OGG File Source</name>
<key>satnogs_ogg_source</key>
<category>[satnogs]</category>
<import>import satnogs</import>
<make>satnogs.ogg_source($filename, $channels)</make>
<param>
<name>File</name>
<key>filename</key>
<value></value>
<type>file_open</type>
</param>
<param>
<name>Channels</name>
<key>channels</key>
<value>1</value>
<type>int</type>
</param>
<source>
<name>out</name>
<type>float</type>
<nports>$channels</nports>
</source>
</block>

View File

@ -63,5 +63,5 @@ if(${INCLUDE_DEBUG_BLOCKS})
endif()
install(FILES
${HEADER_FILES}
DESTINATION include/satnogs
ogg_source.h DESTINATION include/satnogs
)

View File

@ -0,0 +1,59 @@
/* -*- c++ -*- */
/*
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
*
* Copyright (C) 2017, Libre Space Foundation <http://librespacefoundation.org/>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef INCLUDED_SATNOGS_OGG_SOURCE_H
#define INCLUDED_SATNOGS_OGG_SOURCE_H
#include <satnogs/api.h>
#include <gnuradio/sync_block.h>
namespace gr
{
namespace satnogs
{
/*!
* \brief OGG source block. Reads a file with an OGG audio and
* convert it to float samples
*
* \ingroup satnogs
*
*/
class SATNOGS_API ogg_source : virtual public gr::sync_block
{
public:
typedef boost::shared_ptr<ogg_source> sptr;
/*!
*
* @param filename the OGG audio file path
* @param number of channels of the OGG stream. If the actual OGG stream
* contains a different number of channels than specified an exception
* is raised
*/
static sptr
make (const std::string& filename, size_t channels = 1);
};
} // namespace satnogs
} // namespace gr
#endif /* INCLUDED_SATNOGS_OGG_SOURCE_H */

View File

@ -59,7 +59,8 @@ list(APPEND satnogs_sources
ax25_encoder_mb_impl.cc
ax25_decoder_bm_impl.cc
qb50_deframer_impl.cc
waterfall_sink_impl.cc)
waterfall_sink_impl.cc
ogg_source_impl.cc)
if(${INCLUDE_DEBUG_BLOCKS})
list(APPEND satnogs_sources ${satnogs_debug_sources})

125
lib/ogg_source_impl.cc Normal file
View File

@ -0,0 +1,125 @@
/* -*- c++ -*- */
/*
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
*
* Copyright (C) 2017, Libre Space Foundation <http://librespacefoundation.org/>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gnuradio/io_signature.h>
#include <vorbis/codec.h>
#include <vorbis/vorbisfile.h>
#include <volk/volk.h>
#include "ogg_source_impl.h"
#define PCM_BUF_SIZE 4096
namespace gr {
namespace satnogs {
ogg_source::sptr
ogg_source::make(const std::string& filename, size_t channels)
{
return gnuradio::get_initial_sptr
(new ogg_source_impl(filename, channels));
}
/*
* The private constructor
*/
ogg_source_impl::ogg_source_impl (const std::string& filename,
size_t channels) :
gr::sync_block (
"ogg_source", gr::io_signature::make (0, 0, 0),
gr::io_signature::make (channels, channels, sizeof(float))),
d_channels (channels)
{
if (channels < 1) {
throw std::invalid_argument ("At least one output channels should"
" be specified");
}
if (ov_fopen (filename.c_str (), &d_ogvorb_f) < 0) {
throw std::invalid_argument ("Invalid .ogg file");
}
vorbis_info *vi = ov_info(&d_ogvorb_f,-1);
if(vi->channels != (int) channels) {
throw std::invalid_argument (
std::string ("Channels number specified (")
+ std::to_string (channels)
+ ") does not match the channels of "
"the ogg stream (" + std::to_string (vi->channels) + ")");
}
const int alignment_multiple = volk_get_alignment() / sizeof(float);
set_alignment(std::max(1,alignment_multiple));
set_max_noutput_items(PCM_BUF_SIZE);
d_in_buffer = (int16_t *)volk_malloc(PCM_BUF_SIZE * sizeof(int16_t),
volk_get_alignment());
d_out_buffer = (float *)volk_malloc(PCM_BUF_SIZE * sizeof(float),
volk_get_alignment());
}
/*
* Our virtual destructor.
*/
ogg_source_impl::~ogg_source_impl()
{
ov_clear(&d_ogvorb_f);
volk_free(d_in_buffer);
volk_free(d_out_buffer);
}
int
ogg_source_impl::work(int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
long int ret;
int section = 0;
int available = (noutput_items / d_channels);
int produced = 0;
ret = ov_read (&d_ogvorb_f, (char *)d_in_buffer,
available * sizeof(int16_t),
0, sizeof(int16_t), 1, &section);
if(ret < sizeof(int16_t)) {
return WORK_DONE;
}
/* Convert to float the signed-short audio samples */
volk_16i_s32f_convert_32f (d_out_buffer, d_in_buffer, 2 << 15,
ret / sizeof(int16_t));
/* De-interleave the available channels */
for(int i = 0; i < ret / sizeof(int16_t); i += d_channels, produced++) {
for(int chan = 0; chan < d_channels; chan++){
((float *)output_items[chan])[produced] = d_out_buffer[i * d_channels + chan];
}
}
return produced;
}
} /* namespace satnogs */
} /* namespace gr */

56
lib/ogg_source_impl.h Normal file
View File

@ -0,0 +1,56 @@
/* -*- c++ -*- */
/*
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
*
* Copyright (C) 2017, Libre Space Foundation <http://librespacefoundation.org/>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef INCLUDED_SATNOGS_OGG_SOURCE_IMPL_H
#define INCLUDED_SATNOGS_OGG_SOURCE_IMPL_H
#include <satnogs/ogg_source.h>
#include <vorbis/codec.h>
#include <vorbis/vorbisfile.h>
namespace gr
{
namespace satnogs
{
class ogg_source_impl : public ogg_source
{
private:
const size_t d_channels;
OggVorbis_File d_ogvorb_f;
int16_t *d_in_buffer;
float *d_out_buffer;
public:
ogg_source_impl (const std::string& filename, size_t channels);
~ogg_source_impl ();
// Where all the action really happens
int
work (int noutput_items, gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
};
} // namespace satnogs
} // namespace gr
#endif /* INCLUDED_SATNOGS_OGG_SOURCE_IMPL_H */

View File

@ -32,6 +32,7 @@
#include "satnogs/qb50_deframer.h"
#include "satnogs/waterfall_sink.h"
#include "satnogs/ogg_encoder.h"
#include "satnogs/ogg_source.h"
%}
@ -100,3 +101,5 @@ GR_SWIG_BLOCK_MAGIC2(satnogs, qb50_deframer);
GR_SWIG_BLOCK_MAGIC2(satnogs, waterfall_sink);
%include "satnogs/ogg_encoder.h"
GR_SWIG_BLOCK_MAGIC2(satnogs, ogg_encoder);
%include "satnogs/ogg_source.h"
GR_SWIG_BLOCK_MAGIC2(satnogs, ogg_source);