diff --git a/CMakeLists.txt b/CMakeLists.txt index c59725c..112e1f7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -116,6 +116,7 @@ find_package (Threads REQUIRED) find_package(CppUnit) find_package(Doxygen) find_package(Volk REQUIRED) +find_package(OggVorbis REQUIRED) ######################################################################## # Include or not into the module blocks for debugging diff --git a/cmake/Modules/FindOggVorbis.cmake b/cmake/Modules/FindOggVorbis.cmake new file mode 100644 index 0000000..32835b0 --- /dev/null +++ b/cmake/Modules/FindOggVorbis.cmake @@ -0,0 +1,86 @@ +# - Try to find the OggVorbis libraries +# Once done this will define +# +# OGGVORBIS_FOUND - system has OggVorbis +# OGGVORBIS_VERSION - set either to 1 or 2 +# OGG_INCLUDE_DIR - the OggVorbis include directory +# VORBIS_INCLUDE_DIR - the OggVorbis include directory +# OGGVORBIS_LIBRARIES - The libraries needed to use OggVorbis +# OGG_LIBRARY - The Ogg library +# VORBIS_LIBRARY - The Vorbis library +# VORBISFILE_LIBRARY - The VorbisFile library +# VORBISENC_LIBRARY - The VorbisEnc library + +# Copyright (c) 2006, Richard Laerkaeng, +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + + +include (CheckLibraryExists) + +find_path(VORBIS_INCLUDE_DIR vorbis/vorbisfile.h) +find_path(OGG_INCLUDE_DIR ogg/ogg.h) + +find_library(OGG_LIBRARY NAMES ogg) +find_library(VORBIS_LIBRARY NAMES vorbis) +find_library(VORBISFILE_LIBRARY NAMES vorbisfile) +find_library(VORBISENC_LIBRARY NAMES vorbisenc) + + +if (VORBIS_INCLUDE_DIR AND VORBIS_LIBRARY AND VORBISFILE_LIBRARY AND VORBISENC_LIBRARY) + set(OGGVORBIS_FOUND TRUE) + + set(OGGVORBIS_LIBRARIES ${OGG_LIBRARY} ${VORBIS_LIBRARY} ${VORBISFILE_LIBRARY} ${VORBISENC_LIBRARY}) + + set(_CMAKE_REQUIRED_LIBRARIES_TMP ${CMAKE_REQUIRED_LIBRARIES}) + set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${OGGVORBIS_LIBRARIES}) + check_library_exists(vorbis vorbis_bitrate_addblock "" HAVE_LIBVORBISENC2) + set(CMAKE_REQUIRED_LIBRARIES ${_CMAKE_REQUIRED_LIBRARIES_TMP}) + + if (HAVE_LIBVORBISENC2) + set (OGGVORBIS_VERSION 2) + else (HAVE_LIBVORBISENC2) + set (OGGVORBIS_VERSION 1) + endif (HAVE_LIBVORBISENC2) + +else (VORBIS_INCLUDE_DIR AND VORBIS_LIBRARY AND VORBISFILE_LIBRARY AND VORBISENC_LIBRARY) + set (OGGVORBIS_VERSION) + set(OGGVORBIS_FOUND FALSE) +endif (VORBIS_INCLUDE_DIR AND VORBIS_LIBRARY AND VORBISFILE_LIBRARY AND VORBISENC_LIBRARY) + + +if (OGGVORBIS_FOUND) + if (NOT OggVorbis_FIND_QUIETLY) + message(STATUS "Found OggVorbis: ${OGGVORBIS_LIBRARIES}") + endif (NOT OggVorbis_FIND_QUIETLY) +else (OGGVORBIS_FOUND) + if (OggVorbis_FIND_REQUIRED) + message(FATAL_ERROR "Could NOT find OggVorbis libraries") + endif (OggVorbis_FIND_REQUIRED) + if (NOT OggVorbis_FIND_QUITELY) + message(STATUS "Could NOT find OggVorbis libraries") + endif (NOT OggVorbis_FIND_QUITELY) +endif (OGGVORBIS_FOUND) + +#check_include_files(vorbis/vorbisfile.h HAVE_VORBISFILE_H) +#check_library_exists(ogg ogg_page_version "" HAVE_LIBOGG) +#check_library_exists(vorbis vorbis_info_init "" HAVE_LIBVORBIS) +#check_library_exists(vorbisfile ov_open "" HAVE_LIBVORBISFILE) +#check_library_exists(vorbisenc vorbis_info_clear "" HAVE_LIBVORBISENC) +#check_library_exists(vorbis vorbis_bitrate_addblock "" HAVE_LIBVORBISENC2) + +#if (HAVE_LIBOGG AND HAVE_VORBISFILE_H AND HAVE_LIBVORBIS AND HAVE_LIBVORBISFILE AND HAVE_LIBVORBISENC) +# message(STATUS "Ogg/Vorbis found") +# set (VORBIS_LIBS "-lvorbis -logg") +# set (VORBISFILE_LIBS "-lvorbisfile") +# set (VORBISENC_LIBS "-lvorbisenc") +# set (OGGVORBIS_FOUND TRUE) +# if (HAVE_LIBVORBISENC2) +# set (HAVE_VORBIS 2) +# else (HAVE_LIBVORBISENC2) +# set (HAVE_VORBIS 1) +# endif (HAVE_LIBVORBISENC2) +#else (HAVE_LIBOGG AND HAVE_VORBISFILE_H AND HAVE_LIBVORBIS AND HAVE_LIBVORBISFILE AND HAVE_LIBVORBISENC) +# message(STATUS "Ogg/Vorbis not found") +#endif (HAVE_LIBOGG AND HAVE_VORBISFILE_H AND HAVE_LIBVORBIS AND HAVE_LIBVORBISFILE AND HAVE_LIBVORBISENC) \ No newline at end of file diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt index 40a7195..c79e908 100644 --- a/grc/CMakeLists.txt +++ b/grc/CMakeLists.txt @@ -31,6 +31,7 @@ list(APPEND enabled_blocks satnogs_cw_matched_filter_ff.xml satnogs_morse_decoder.xml satnogs_multi_format_msg_sink.xml + satnogs_ogg_encoder.xml satnogs_cw_to_symbol.xml satnogs_sine_matched_filter_ff.xml satnogs_udp_msg_source.xml @@ -48,5 +49,5 @@ if(${INCLUDE_DEBUG_BLOCKS}) endif() install(FILES ${enabled_blocks} - DESTINATION share/gnuradio/grc/blocks + DESTINATION share/gnuradio/grc/blocks ) diff --git a/grc/satnogs_block_tree.xml b/grc/satnogs_block_tree.xml index ee61c74..52f236b 100644 --- a/grc/satnogs_block_tree.xml +++ b/grc/satnogs_block_tree.xml @@ -13,6 +13,7 @@ satnogs_cw_matched_filter_ff satnogs_morse_decoder satnogs_multi_format_msg_sink + satnogs_ogg_encoder satnogs_cw_to_symbol satnogs_sine_matched_filter_ff satnogs_udp_msg_source diff --git a/grc/satnogs_ogg_encoder.xml b/grc/satnogs_ogg_encoder.xml new file mode 100644 index 0000000..6154ded --- /dev/null +++ b/grc/satnogs_ogg_encoder.xml @@ -0,0 +1,32 @@ + + + OGG Encoder + satnogs_ogg_encoder + import satnogs + satnogs.ogg_encoder($filename, $samp_rate, $quality) + + + File + filename + + file_save + + + + Sampling rate + samp_rate + real + + + + Quality + quality + 0.8 + real + + + + in + float + + diff --git a/include/satnogs/CMakeLists.txt b/include/satnogs/CMakeLists.txt index 847f492..2c16dc5 100644 --- a/include/satnogs/CMakeLists.txt +++ b/include/satnogs/CMakeLists.txt @@ -37,6 +37,7 @@ list(APPEND HEADER_FILES morse.h morse_decoder.h multi_format_msg_sink.h + ogg_encoder.h cw_to_symbol.h sine_matched_filter_ff.h utils.h @@ -61,6 +62,6 @@ if(${INCLUDE_DEBUG_BLOCKS}) list(APPEND HEADER_FILES ${DEBUG_HEADER_FILES}) endif() install(FILES - ${HEADER_FILES} + ${HEADER_FILES} DESTINATION include/satnogs ) \ No newline at end of file diff --git a/include/satnogs/ogg_encoder.h b/include/satnogs/ogg_encoder.h new file mode 100644 index 0000000..18bd62c --- /dev/null +++ b/include/satnogs/ogg_encoder.h @@ -0,0 +1,55 @@ +/* -*- c++ -*- */ +/* + * gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module + * + * Copyright (C) 2017, Libre Space Foundation + * + * 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 . + */ + +#ifndef INCLUDED_SATNOGS_OGG_ENCODER_H +#define INCLUDED_SATNOGS_OGG_ENCODER_H + +#include +#include + +namespace gr +{ + namespace satnogs + { + + /*! + * \brief Ogg encoder and sink block + * \ingroup satnogs + * + */ + class SATNOGS_API ogg_encoder : virtual public gr::sync_block + { + public: + typedef boost::shared_ptr sptr; + + /*! + * Ogg encoder and sink block. + * @param filename filename of the output file + * @param samp_rate the sampling rate + * @param quality the quality of the output file. [0.1 - 1.0] (worst - best) + */ + static sptr + make (char* filename, double samp_rate, float quality); + }; + + } // namespace satnogs +} // namespace gr + +#endif /* INCLUDED_SATNOGS_OGG_ENCODER_H */ diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index aeb1960..15bcb14 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -25,6 +25,8 @@ include(GrPlatform) #define LIB_SUFFIX include_directories( ${Boost_INCLUDE_DIR} ${VOLK_INCLUDE_DIRS} + ${VORBIS_INCLUDE_DIR} + ${OGG_INCLUDE_DIR} ) link_directories(${Boost_LIBRARY_DIRS}) @@ -40,6 +42,7 @@ list(APPEND satnogs_sources morse_tree.cc morse_decoder_impl.cc multi_format_msg_sink_impl.cc + ogg_encoder_impl.cc cw_to_symbol_impl.cc sine_matched_filter_ff_impl.cc udp_msg_source_impl.cc @@ -56,7 +59,7 @@ 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) if(${INCLUDE_DEBUG_BLOCKS}) list(APPEND satnogs_sources ${satnogs_debug_sources}) @@ -76,6 +79,7 @@ target_link_libraries(gnuradio-satnogs ${CMAKE_THREAD_LIBS_INIT} ${NOVA_LIBRARIES} ${VOLK_LIBRARIES} + ${OGGVORBIS_LIBRARIES} ) set_target_properties(gnuradio-satnogs PROPERTIES DEFINE_SYMBOL "gnuradio_satnogs_EXPORTS") diff --git a/lib/ogg_encoder_impl.cc b/lib/ogg_encoder_impl.cc new file mode 100644 index 0000000..b07f232 --- /dev/null +++ b/lib/ogg_encoder_impl.cc @@ -0,0 +1,137 @@ +/* -*- c++ -*- */ +/* + * gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module + * + * Copyright (C) 2017, Libre Space Foundation + * + * 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 . + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "ogg_encoder_impl.h" + +#include +#include +#include +#include +#include + +namespace gr +{ + namespace satnogs + { + + ogg_encoder::sptr + ogg_encoder::make (char* filename, double samp_rate, float quality) + { + return gnuradio::get_initial_sptr ( + new ogg_encoder_impl (filename, samp_rate, quality)); + } + + /* + * The private constructor + */ + ogg_encoder_impl::ogg_encoder_impl (char* filename, double samp_rate, + float quality) : + gr::sync_block ("ogg_encoder", + gr::io_signature::make (1, 1, sizeof(float)), + gr::io_signature::make (0, 0, 0)) + { + d_quality = quality; + d_out = fopen (filename, "wb"); + d_samp_rate = samp_rate; + vorbis_info_init (&d_vi); + int ret = vorbis_encode_init_vbr (&d_vi, 1, d_samp_rate, d_quality); + if (ret) + exit (1); + + vorbis_comment_init (&d_vc); + vorbis_comment_add_tag (&d_vc, "ENCODER", "satnogs ogg encoder"); + + vorbis_analysis_init (&d_vd, &d_vi); + vorbis_block_init (&d_vd, &d_vb); + + srand (time (NULL)); + ogg_stream_init (&d_os, rand ()); + + ogg_packet header; + ogg_packet header_comm; + ogg_packet header_code; + + vorbis_analysis_headerout (&d_vd, &d_vc, &header, &header_comm, + &header_code); + ogg_stream_packetin (&d_os, &header); + ogg_stream_packetin (&d_os, &header_comm); + ogg_stream_packetin (&d_os, &header_code); + int result = 1; + while (result) { + result = ogg_stream_flush (&d_os, &d_og); + if (result == 0) + break; + fwrite (d_og.header, 1, d_og.header_len, d_out); + fwrite (d_og.body, 1, d_og.body_len, d_out); + } + } + + ogg_encoder_impl::~ogg_encoder_impl () + { + vorbis_analysis_wrote (&d_vd, 0); + ogg_stream_clear (&d_os); + vorbis_block_clear (&d_vb); + vorbis_dsp_clear (&d_vd); + vorbis_comment_clear (&d_vc); + vorbis_info_clear (&d_vi); + fclose (d_out); + } + + int + ogg_encoder_impl::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const char *in = (const char *) input_items[0]; + int i; + float **buffer = vorbis_analysis_buffer (&d_vd, noutput_items); + memcpy(buffer[0], in, noutput_items * sizeof(float)); + + vorbis_analysis_wrote (&d_vd, noutput_items); + + while (vorbis_analysis_blockout (&d_vd, &d_vb) == 1) { + vorbis_analysis (&d_vb, NULL); + vorbis_bitrate_addblock (&d_vb); + + while (vorbis_bitrate_flushpacket (&d_vd, &d_op)) { + + ogg_stream_packetin (&d_os, &d_op); + int result = 1; + while (result) { + int result = ogg_stream_pageout (&d_os, &d_og); + if (result == 0) + break; + fwrite (d_og.header, 1, d_og.header_len, d_out); + fwrite (d_og.body, 1, d_og.body_len, d_out); + if (ogg_page_eos (&d_og)) + result = 1; + } + } + } + return noutput_items; + } + + } /* namespace satnogs */ +} /* namespace gr */ diff --git a/lib/ogg_encoder_impl.h b/lib/ogg_encoder_impl.h new file mode 100644 index 0000000..c8cf28b --- /dev/null +++ b/lib/ogg_encoder_impl.h @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module + * + * Copyright (C) 2017, Libre Space Foundation + * + * 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 . + */ + +#ifndef INCLUDED_SATNOGS_OGG_ENCODER_IMPL_H +#define INCLUDED_SATNOGS_OGG_ENCODER_IMPL_H + +#include +#include + +namespace gr +{ + namespace satnogs + { + + class ogg_encoder_impl : public ogg_encoder + { + private: + // Nothing to declare in this block. + ogg_stream_state d_os; + ogg_page d_og; + ogg_packet d_op; + + vorbis_info d_vi; + vorbis_comment d_vc; + + vorbis_dsp_state d_vd; + vorbis_block d_vb; + FILE* d_out; + double d_samp_rate; + float d_quality; + + public: + ogg_encoder_impl (char* filename, double samp_rate, float quality); + ~ogg_encoder_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_ENCODER_IMPL_H */ diff --git a/swig/satnogs_swig.i b/swig/satnogs_swig.i index 4c6b730..8b3417a 100644 --- a/swig/satnogs_swig.i +++ b/swig/satnogs_swig.i @@ -31,6 +31,7 @@ #include "satnogs/ax25_decoder_bm.h" #include "satnogs/qb50_deframer.h" #include "satnogs/waterfall_sink.h" +#include "satnogs/ogg_encoder.h" %} @@ -97,3 +98,5 @@ GR_SWIG_BLOCK_MAGIC2(satnogs, qb50_deframer); %include "satnogs/waterfall_sink.h" GR_SWIG_BLOCK_MAGIC2(satnogs, waterfall_sink); +%include "satnogs/ogg_encoder.h" +GR_SWIG_BLOCK_MAGIC2(satnogs, ogg_encoder);