forked from sletz/faust-mcp
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathanalysis_arch.cpp
More file actions
171 lines (142 loc) · 6.01 KB
/
analysis_arch.cpp
File metadata and controls
171 lines (142 loc) · 6.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
/**
* Faust analysis architecture example.
*
* Renders DSP output offline, computes basic amplitude metrics, and prints
* a JSON report including ASCII waveform summaries.
*/
#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
#include <string>
// Faust interface requirements
#include "faust/gui/MapUI.h"
#include "faust/gui/meta.h"
#include "faust/dsp/dsp.h"
/******************************************************************************
*******************************************************************************
VECTOR INTRINSICS
*******************************************************************************
*******************************************************************************/
<<includeIntrinsic>>
/********************END ARCHITECTURE SECTION (part 1/2)****************/
/**************************BEGIN USER SECTION **************************/
<<includeclass>>
/***************************END USER SECTION ***************************/
/*******************BEGIN ARCHITECTURE SECTION (part 2/2)***************/
// -- ASCII Art Helper --
/**
* Create a compact ASCII waveform summary for a buffer.
*
* Returns a string of length `width` with characters chosen from the
* local min/max amplitude range in each bucket.
*/
std::string asciiWaveform(const std::vector<float>& buffer, int width, int height)
{
std::string out = "";
int step = buffer.size() / width;
for (int i = 0; i < width; i++) {
float maxVal = -1.0f;
float minVal = 1.0f;
// Find min/max in this chunk
for (int j = 0; j < step && (i*step + j) < buffer.size(); j++) {
float val = buffer[i*step + j];
if (val > maxVal) maxVal = val;
if (val < minVal) minVal = val;
}
// Simple visualization: stick to one char based on amplitude
if (maxVal < 0.01 && minVal > -0.01) out += "_";
else if (maxVal > 0.5) out += "#";
else if (maxVal > 0.2) out += "=";
else out += "-";
}
return out;
}
/**
* Render the compiled DSP, analyze output levels, and print a JSON report.
*/
int main(int argc, char* argv[])
{
// 1. Instantiate the DSP (The class name 'mydsp' is standard in Faust compilation)
mydsp DSP;
int sr = 44100;
int samples = 44100 * 2; // Analyze 2 seconds
DSP.init(sr);
// 2. Prepare Audio Buffers
int inputs = DSP.getNumInputs();
int outputs = DSP.getNumOutputs();
// We only support generators (0 inputs) for this simplified test
// or simple effects processing silence
float** input_buffers = new float*[inputs];
for (int i = 0; i < inputs; i++) {
input_buffers[i] = new float[samples];
std::fill(input_buffers[i], input_buffers[i] + samples, 0.0f);
}
float** output_buffers = new float*[outputs];
for (int i = 0; i < outputs; i++) output_buffers[i] = new float[samples];
// 3. Render Audio (Block by block processing simulated in one go for simplicity here)
// For Faust class, we usually compute small blocks, but here lets do ne big block
// if the memory allows, or loop. Let's loop 1024 frames.
int blockSize = 256;
int computed = 0;
// Create UI to pass default params
MapUI ui;
DSP.buildUserInterface(&ui);
// Metrics (global + per-channel)
float maxAmp = 0.0;
float sumSq = 0.0;
std::vector<float> monoMix; // To visualize (global)
std::vector<float> chanMax(outputs, 0.0f);
std::vector<float> chanSumSq(outputs, 0.0f);
std::vector<std::vector<float>> chanWave(outputs);
while (computed < samples) {
// Pointers for this block
float* ib[inputs];
float* ob[outputs];
for (int i = 0; i < inputs; i++) ib[i] = input_buffers[i] + computed;
for (int i = 0; i < outputs; i++) ob[i] = output_buffers[i] + computed;
int n = std::min(blockSize, samples - computed);
DSP.compute(n, ib, ob);
// Analyze this block
for (int i = 0; i < n; i++) {
float val = 0.0;
// Per-channel metrics + sum to mono
for (int c = 0; c < outputs; c++) {
float cval = ob[c][i];
if (std::abs(cval) > chanMax[c]) chanMax[c] = std::abs(cval);
chanSumSq[c] += cval * cval;
chanWave[c].push_back(cval);
val += cval;
}
if (outputs > 0) val /= (float)outputs; // Average
if (std::abs(val) > maxAmp) maxAmp = std::abs(val);
sumSq += val * val;
monoMix.push_back(val);
}
computed += n;
}
float rms = std::sqrt(sumSq / samples);
// 4. Output JSON for the MCP Server
std::cout << "{" << std::endl;
std::cout << " \"status\": \"success\"," << std::endl;
std::cout << " \"max_amplitude\": " << maxAmp << "," << std::endl;
std::cout << " \"rms\": " << rms << "," << std::endl;
std::cout << " \"is_silent\": " << (maxAmp < 0.0001 ? "true" : "false") << "," << std::endl;
std::cout << " \"waveform_ascii\": \"" << asciiWaveform(monoMix, 60, 10) << "\"," << std::endl;
std::cout << " \"num_outputs\": " << outputs << "," << std::endl;
std::cout << " \"channels\": [" << std::endl;
for (int c = 0; c < outputs; c++) {
float crms = std::sqrt(chanSumSq[c] / samples);
bool csilent = chanMax[c] < 0.0001f;
std::cout << " {" << std::endl;
std::cout << " \"index\": " << c << "," << std::endl;
std::cout << " \"max_amplitude\": " << chanMax[c] << "," << std::endl;
std::cout << " \"rms\": " << crms << "," << std::endl;
std::cout << " \"is_silent\": " << (csilent ? "true" : "false") << "," << std::endl;
std::cout << " \"waveform_ascii\": \"" << asciiWaveform(chanWave[c], 60, 10) << "\"" << std::endl;
std::cout << " }" << (c == outputs - 1 ? "" : ",") << std::endl;
}
std::cout << " ]" << std::endl;
std::cout << "}" << std::endl;
return 0;
}