Viking Skull Lamp  V1.0.1
Loading...
Searching...
No Matches
musicVisualizer.cpp
Go to the documentation of this file.
1/*
2 * Created on May 28 2022
3 *
4 * Copyright (c) 2022 - Daniel Hajnal
5 * hajnal.daniel96@gmail.com
6 * This file is part of the Viking Skull Lamp project.
7 * Modified 2022.06.27
8*/
9
10/*
11MIT License
12Copyright (c) 2022 Daniel Hajnal
13Permission is hereby granted, free of charge, to any person obtaining a copy
14of this software and associated documentation files (the "Software"), to deal
15in the Software without restriction, including without limitation the rights
16to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17copies of the Software, and to permit persons to whom the Software is
18furnished to do so, subject to the following conditions:
19The above copyright notice and this permission notice shall be included in all
20copies or substantial portions of the Software.
21THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27SOFTWARE.
28*/
29
30#include "musicVisualizer.hpp"
31
32musicChannel::musicChannel( int pin_p, float silentLimit_p ){
33
34 // Store arguments to internal variables.
35 pin = pin_p;
36 silentLimit = silentLimit_p;
37
38}
39
40musicChannel::musicChannel( int pin_p, float silentLimit_p, float offset_p ){
41
42 // Store arguments to internal variables.
43 pin = pin_p;
44 silentLimit = silentLimit_p;
45 offset = offset_p;
46
47}
48
49musicChannel::musicChannel( int pin_p, float silentLimit_p, float offset_p, float avgSampleFilterBeta_p, float sampleFilterBeta_p ){
50
51 // Store arguments to internal variables.
52 pin = pin_p;
53 silentLimit = silentLimit_p;
54 offset = offset_p;
55 avgSampleFilterBeta = avgSampleFilterBeta_p;
56 sampleFilterBeta = sampleFilterBeta_p;
57
58}
59
60void musicChannel::attachPeakFunction( void(*peakFunc_p)(void) ){
61
62 // Store function pointer to internal variable.
63 peakFunc = peakFunc_p;
64
65}
66
68
69 // Offset the raw signal to make it act like in the real world.
70 sample = (float)analogRead( pin ) - offset;
71
72 // If the signal has negative component flip it to the positive range.
73 sample = abs( sample );
74
75 // Generate the average sample with a complementary filter.
76 avgSample = ( ( (float)sample ) * avgSampleFilterBeta + avgSample * ( 1.0 - avgSampleFilterBeta ) );
77
78 // In cases when the signal is too low, make it 0 to no trigger any event.
79 if( ( sample < ( avgSample / 2 ) ) || ( sample < silentLimit ) ){
80
81 signal = 0;
82
83 }
84
85 // If the signal is strong enough, filter it with a complementary filter.
86 else{
87
89
90 }
91
92 // Always reduce the value of the signalMax variable. It is necessary for
93 // noise floor level compensation. I think -10.0 per iteration is suitable.
94 signalMax -= 10.0;
95
96 // Limit it to 0.
97 if( signalMax < 0.0 ){
98
99 signalMax = 0.0;
100
101 }
102
103 // If the signal is above the stored max level,
104 // save the max level.
105 if( signalMax < signal ){
106
108
109 }
110
111 // If the signal changes rapidly we have to recalculate the average peak.
112 if( ( ( signal - signalPrev ) > ( avgSample - signalPrev ) ) && ( ( avgSample - signalPrev ) > 0 ) ){
113
114 avgPeak = ( avgPeak + ( signal - signalPrev ) ) / 2.0;
115
116 }
117
118 // If the signal change is greater than the average peak, it means we have a peak event.
119 peak = ( signal - signalPrev ) > avgPeak;
120
121 // If peak event occured, and peakFunction is attached, call that function.
122 if( peak && ( peakFunc != NULL ) ){
123
124 peakFunc();
125
126 }
127
128 // Change the signal to the signalPrev variable.
130
131}
132
133musicChannel peak( SOUND_PEAK, 20.0, 0.0, 0.5, 0.5 );
This object is used to process audio data.
float signal
The filtered signal will be stored in this variable.
void update()
Update function.
float signalMax
The maximum level of the signal is stored in this variable.
int pin
Analog input pin of the channel.
float avgPeak
Average peak signal.
float sample
The raw sample will be processed to this variable.
float silentLimit
Silent limit.
musicChannel(int pin_p, float silentLimit_p)
Constructor.
float offset
Offset of the ADC result.
void(* peakFunc)(void)
Function pointer to peak event function.
float avgSampleFilterBeta
Filter constant for average sample.
float sampleFilterBeta
Filter constant for sample.
void attachPeakFunction(void(*peakFunc_p)(void))
Attach a function to every peak event.
float signalPrev
Previous value of the signal.
float avgSample
Holds the average filter level.
bool peak
Flag, that indicates a peak event.
musicChannel peak(SOUND_PEAK, 20.0, 0.0, 0.5, 0.5)
#define SOUND_PEAK
The peak-detector is connected to pin A2 on the Arduino.