Skip to content

Instantly share code, notes, and snippets.

@bolero-MURAKAMI
Created December 3, 2012 12:39
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bolero-MURAKAMI/4194789 to your computer and use it in GitHub Desktop.
Save bolero-MURAKAMI/4194789 to your computer and use it in GitHub Desktop.
#ifndef APP_WAVE_IO_HPP
#define APP_WAVE_IO_HPP
#include <cstddef>
#include <cstdint>
#include <climits>
#include <string>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <type_traits>
#include <sprout/compost/sources.hpp>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <linux/soundcard.h>
//
// gnuplot 用の出力
//
template<typename Elem, typename Traits, typename InputRange>
std::basic_ostream<Elem, Traits>& output_plot(std::basic_ostream<Elem, Traits>& os, InputRange const& range) {
os << std::fixed;
unsigned x = 0;
for (auto const& e : range) {
os << x++ << ',' << e << '\n';
}
return os;
}
template<typename InputRange>
void output_plot(std::string const& filename, InputRange const& range) {
std::ofstream os(filename);
output_plot(os, range);
}
//
// gnuplot 用の出力 (複素数の実数成分のみ)
//
template<typename Elem, typename Traits, typename InputRange>
std::basic_ostream<Elem, Traits>& output_plot_real(std::basic_ostream<Elem, Traits>& os, InputRange const& range) {
os << std::fixed;
unsigned x = 0;
for (auto const& e : range) {
os << x++ << ',' << real(e) << '\n';
}
return os;
}
template<typename InputRange>
void output_plot_real(std::string const& filename, InputRange const& range) {
std::ofstream os(filename);
output_plot_real(os, range);
}
//
// wave 形式の書き込み
//
template<typename OutputIterator>
void write_chunk(OutputIterator& it, std::string const& s) {
it = std::copy(s.begin(), s.end(), it);
}
template<typename IntType, typename OutputIterator>
void write_int(OutputIterator& it, IntType const& n) {
for (std::size_t i = 0; i != sizeof(IntType); ++i, ++it) {
*it = static_cast<char>((static_cast<typename std::make_unsigned<IntType>::type>(n) >> (i * CHAR_BIT)) & 0xFF);
}
}
template<typename OutputIterator>
void write_wav_header(OutputIterator& it, sprout::compost::sources::info_type const& info) {
std::size_t data_size = info.size * info.bits_per_sample;
write_chunk(it, "RIFF");
write_int(it, 36 + data_size);
write_chunk(it, "WAVE");
write_chunk(it, "fmt ");
write_int(it, 16);
write_int(it, info.format_tag);
write_int(it, info.channels);
write_int(it, info.samples_per_sec);
write_int(it, info.bytes_per_sec);
write_int(it, info.block_size);
write_int(it, info.bits_per_sample);
write_chunk(it, "data");
write_int(it, data_size);
}
template<typename OutputIterator, typename InputRange>
void write_wav_data(OutputIterator& it, sprout::compost::sources::info_type const& info, InputRange const& data) {
if (info.bits_per_sample == 16) {
for (auto e : data) {
write_int<std::int16_t>(it, e);
}
} else if (info.bits_per_sample == 8) {
for (auto e : data) {
write_int<std::uint8_t>(it, e);
}
}
}
template<typename OutputIterator, typename InputRange>
void write_wav(OutputIterator& it, sprout::compost::sources::info_type const& info, InputRange const& data) {
write_wav_header(it, info);
write_wav_data(it, info, data);
}
//
// wave 形式の出力
//
template<typename Elem, typename Traits, typename InputRange>
void output_wav(std::basic_ostream<Elem, Traits>& os, sprout::compost::sources::info_type const& info, InputRange const& data) {
std::ostreambuf_iterator<Elem> it(os);
write_wav(it, info, data);
}
template<typename InputRange>
void output_wav(std::string const& filename, sprout::compost::sources::info_type const& info, InputRange const& data) {
std::ofstream os(filename, std::ios_base::out | std::ios_base::binary);
output_wav(os, info, data);
}
template<typename Elem, typename Traits, typename InputRanges>
void output_wav_blocks(std::basic_ostream<Elem, Traits>& os, sprout::compost::sources::info_type const& info, InputRanges const& data) {
std::ostreambuf_iterator<Elem> it(os);
write_wav_header(it, info);
for (auto const& e : data) {
write_wav_data(it, info, e);
}
}
template<typename InputRanges>
void output_wav_blocks(std::string const& filename, sprout::compost::sources::info_type const& info, InputRanges const& data) {
std::ofstream os(filename, std::ios_base::out | std::ios_base::binary);
output_wav_blocks(os, info, data);
}
//
// dsp デバイスのセットアップ
//
int setup_dev_dsp(sprout::compost::sources::info_type const& info) {
// dsp デバイスのオープン
int fd = open("/dev/dsp", O_RDWR);
if (fd < 0) {
std::cerr << "open of /dev/dsp failed" << std::endl;
return -1;
}
// dsp デバイスの各種初期化
int arg = 0;
int status = 0;
// サンプリングビット
arg = info.bits_per_sample;
status = ioctl(fd, SOUND_PCM_WRITE_BITS, &arg);
if (status == -1 || arg != info.bits_per_sample) {
return -1;
}
// データの種類 ステレオ or モノラル
arg = info.channels;
status = ioctl(fd, SOUND_PCM_WRITE_CHANNELS, &arg);
if (status == -1 || arg != info.channels) {
return -1;
}
// サンプリング周波数
arg = info.samples_per_sec;
status = ioctl(fd, SOUND_PCM_WRITE_RATE, &arg);
if (status == -1 || arg != static_cast<int>(info.samples_per_sec)) {
return -1;
}
return fd;
}
//
// dsp デバイスの書き込み
//
ssize_t write_dev_dsp(int fd, void const* buf, std::size_t n) {
return write(fd, buf, n);
}
#endif // #ifndef APP_WAVE_IO_HPP
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment