arduino-audio-tools
All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends Macros Modules Pages
JupyterAudio.h
1#pragma once
3#include "AudioTools/CoreAudio/AudioStreams.h"
4#include "AudioTools/CoreAudio/AudioOutput.h"
5#include "AudioTools/AudioCodecs/CodecWAV.h"
6#include <string.h>
7#include <iostream>
8#include <fstream>
9#include <filesystem>
10#include <stdio.h>
11#include "nlohmann/json.hpp"
12#include "xtl/xbase64.hpp"
13
14namespace audio_tools {
15
19class FileOutput : public Print {
20public:
21 FileOutput(std::fstream &stream){
22 p_audio_stream = &stream;
23 }
24 size_t write(const uint8_t *data, size_t len) override {
25 p_audio_stream->write((const char*)data,len);
26 return len;
27 }
28 int availableForWrite() override {
29 return 1024;
30 }
31protected:
32 std::fstream *p_audio_stream=nullptr;
33};
34
35
40template <typename T>
41class ChartT {
42public:
43 void setup(std::string fName, int channelCount, int channelNo) {
44 this->fname = fName;
45 this->channels = channelCount;
46 if (this->channels==0){
47 LOGE("Setting channels to 0");
48 }
49 this->channel = channelNo;
50 }
51
52 int getChannels() {
53 return this->channels;
54 }
55
56 int getChannel() {
57 return this->channel;
58 }
59
61 const std::string chartData() {
62 str.clear();
63 str.str("");
64 // reset buffer;
65 if (channel<channels){
66 ifstream is;
67 is.open(fname, is.binary);
68 is.seekg(wav_header_size, is.beg);
69 std::list<int16_t> audioList;
70 T buffer[channels];
71 size_t rec_size = channels*sizeof(T);
72 while(is.read((char *)buffer, rec_size)){
73 audioList.push_back(transform(buffer[channel]));
74 }
75 string str_size = "102400"; //std::to_string(audioList.size());
76 str << "<style>div.x-svg {width: "<< str_size <<"px; }</style>";
77 str << "<div class='x-svg'><svg viewBox='0 0 "<< str_size << " 100'> <polyline fill='none' stroke='blue' stroke-width='1' points ='";
78 // copy data from input stream
79 size_t idx = 0;
80 for(int16_t sample: audioList){
81 str << idx++ << "," << sample << " ";
82 }
83 str << "'/></svg></div>";
84 } else {
85 str << "<p>Channel " << channel << " of " << channels << " does not exist!</p>";
86 }
87 return str.str();
88 }
89
90protected:
91 std::stringstream str;
92 std::string fname;
93 const int wav_header_size = 44;
94 int channels=0;
95 int channel=0;
96
97 int transform(int x){
98 int result = x / 1000; // scale -32 to 32
99 result += 60; // shift down
100 return result;
101 }
102};
103
107
112template <typename T>
114public:
115
116 JupyterAudioT(const char* fileName, AudioStream &stream, int bufferCount=20, int bufferSize=1024) {
117 buffer_count = bufferCount;
118 p_audio_stream = &stream;
119 cfg = stream.audioInfo();
120 copier.resize(bufferSize);
121 fname = fileName;
122 if (fileExists()){
123 remove(fileName);
124 }
125 }
126
127 ChartT<T> &chart(int channel=0) {
128 createWAVFile();
129 assert(cfg.channels>0);
130 chrt.setup(fname, cfg.channels, channel);
131 return chrt;
132 }
133
134 // provide the file name
135 const std::string &name() const {
136 return fname;
137 }
138
139 // provides the absolute file path as string
140 const std::string path() const {
141 std::filesystem::path p = fname;
142 std::string result = std::filesystem::absolute(p);
143 return result;
144 }
145
146 // fills a wav file with data once, the first time it was requested
147 void createWAVFile(){
148 try{
149 if (!fileExists()){
150 std::fstream fstream(fname, fstream.binary | fstream.trunc | fstream.out);
151 FileOutput fp(fstream);
152 wave_encoder.setAudioInfo(audioInfo());
153 out.setOutput(&fp);
154 out.setEncoder(&wave_encoder);
155 out.begin(); // output to decoder
156 copier.begin(out, *p_audio_stream);
157 copier.copyN(buffer_count);
158 fstream.close();
159 }
160 } catch(const std::exception& ex){
161 std::cerr << ex.what();
162 }
163 }
164
165 bool fileExists() {
166 ifstream f(fname.c_str());
167 return f.good();
168 }
169
170 int bufferCount(){
171 return buffer_count;
172 }
173
174 // provides the wav data as bas64 encded string
175 std::string audio() {
176 std::ifstream fin(fname, std::ios::binary);
177 std::stringstream m_buffer;
178 m_buffer << fin.rdbuf();
179 return xtl::base64encode(m_buffer.str());
180 }
181
182 // Provides the audion information
184 return cfg;
185 }
186
187protected:
188 AudioStream *p_audio_stream=nullptr;
189 ChartT<T> chrt;
190 WAVEncoder wave_encoder;
192 StreamCopyT<T> copier;
193 AudioInfo cfg;
194 string fname;
195 size_t buffer_count=0;
196};
197
201
202} // namespace audio_tools
203
205nl::json mime_bundle_repr(Chart &in) {
206 auto bundle = nl::json::object();
207 bundle["text/html"] = in.chartData();
208 return bundle;
209}
210
212nl::json mime_bundle_repr(JupyterAudio &in) {
213 auto bundle = nl::json::object();
214 in.createWAVFile();
215 bundle["text/html"] = "<audio controls "
216 "src='data:audio/wav;base64," +
217 in.audio() + "'/>";
218 return bundle;
219}
220
If you want to use the framework w/o Arduino you need to provide the implementation of a couple of cl...
Base class for all Audio Streams. It support the boolean operator to test if the object is ready with...
Definition BaseStream.h:122
virtual AudioInfo audioInfo() override
provides the actual input AudioInfo
Definition BaseStream.h:153
Displays audio in a Jupyter as chart Just wrapps a stream to provide the chart data.
Definition JupyterAudio.h:41
const std::string chartData()
Provides data as svg polyline.
Definition JupyterAudio.h:61
A more natural Print class to process encoded data (aac, wav, mp3...). Just define the output and the...
Definition AudioEncoded.h:21
bool begin() override
Starts the processing - sets the status to active.
Definition AudioEncoded.h:155
void setOutput(Print *outputStream)
Defines the output.
Definition AudioEncoded.h:104
Simple layer for Print object to write to a c++ file.
Definition JupyterAudio.h:19
Output to Jupyter. We write the data just to a file from where we can load the data again for differe...
Definition JupyterAudio.h:113
AudioInfo audioInfo()
provides the actual input AudioInfo
Definition JupyterAudio.h:183
Definition NoArduino.h:62
Typed Stream Copy which supports the conversion from channel to 2 channels. We make sure that we allw...
Definition StreamCopy.h:24
A simple WAV file encoder. If no AudioEncoderExt is specified the WAV file contains PCM data,...
Definition CodecWAV.h:521
virtual void setAudioInfo(AudioInfo from) override
Update actual WAVAudioInfo.
Definition CodecWAV.h:564
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition AudioCodecsBase.h:10
Basic Audio information which drives e.g. I2S.
Definition AudioTypes.h:55
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition AudioTypes.h:59