|
Forum Index : Microcontroller and PC projects : read out carolling christmas bells
| Author | Message | ||||
| twofingers Guru Joined: 02/06/2014 Location: GermanyPosts: 1681 |
Hi Frank, You're not making this easy for us. The WAV format is unusual (type 17) and the signal level is abysmal. I made a first attempt with Cooledit, but only found 8 different tones: D3, D#3, A6, E6, F#6, A7, D7, G7 ![]() That doesn't seem very plausible to me. My suggestion: You could use a better microphone and ring the bells individually. Or check if they might even be stamped? ;-) The storage format shouldn't be ADPCM, but PCM, mono, 16 bits/sample. Kind regards Michael causality ≠ correlation ≠ coincidence |
||||
TassyJim![]() Guru Joined: 07/08/2011 Location: AustraliaPosts: 6363 |
My version of CoolEdit using waterfall display ![]() Frequencies detected (first number is time from start): 0 3500 3200 2130 1500 1210 1060 0.81 2750 1.04 2400 1.3 2130 1.53 2020 1.75 1900 1.99 1800 2.21 1600 2.46 1500 2.69 3500 1400 2.925 1350 3.165 3500 1210 3.41 3200 2130 1060 Code used to convert to notes ' FUNCTION fToNote(toneX AS FLOAT) AS STRING LOCAL FLOAT diff, stdtone, stddiff LOCAL INTEGER noteNum, octave LOCAL allnotes$ = "G#A A#B C C#D D#E F F#G G#A ", noteX$ noteNum = 12*LOG(toneX/440)/LOG(2)+49 ' piano key closest to tone stdtone = 2^((noteNum-49)/12) * 440 ' actual tone of the piano key stddiff = 2^((noteNum-48)/12) * 440 - stdtone ' frequency difference betweem adjacent keys diff = (toneX - stdtone)/stddiff*100 ' error of tone in percent to next note IF noteNum > 87 THEN : octave = 8 ELSEIF noteNum > 75 THEN : octave = 7 ELSEIF noteNum > 63 THEN : octave = 6 ELSEIF noteNum > 51 THEN : octave = 5 ELSEIF noteNum > 39 THEN : octave = 4 ELSEIF noteNum > 27 THEN : octave = 3 ELSEIF noteNum > 15 THEN : octave = 2 ELSEIF noteNum > 3 THEN : octave = 1 ELSE : octave = 0 ENDIF IF noteNum > 0 THEN noteX$ = MID$(allnotes$,(noteNum MOD 12) * 2 +1,2) fToNote = STR$(toneX,8,1)+" Hz "+noteX$+STR$(octave)+STR$(diff,4,0)+"%" ELSE fToNote = STR$(toneX,8,1)+" Hz " ENDIF END FUNCTION PRINT fToNote(3500) PRINT fToNote(3200) PRINT fToNote(2750) PRINT fToNote(2400) PRINT fToNote(2130) PRINT fToNote(2020) PRINT fToNote(1900) PRINT fToNote(1800) PRINT fToNote(1600) PRINT fToNote(1500) PRINT fToNote(1400) PRINT fToNote(1350) PRINT fToNote(1200) PRINT fToNote(1060) DO INPUT "frequency";fr PRINT fToNote(fr) LOOP Results: 3500.0 Hz A 7 -10% 3200.0 Hz G 7 34% 2750.0 Hz F 7 -26% 2400.0 Hz D 7 36% 2130.0 Hz C 7 30% 2020.0 Hz B 6 38% 1900.0 Hz A#6 32% 1800.0 Hz A 6 38% 1600.0 Hz G 6 34% 1500.0 Hz F#6 23% 1400.0 Hz F 6 4% 1350.0 Hz E 6 40% 1200.0 Hz D 6 36% 1060.0 Hz C 6 22% Jim VK7JH MMedit |
||||
| phil99 Guru Joined: 11/02/2018 Location: AustraliaPosts: 2828 |
The first program I tried was unable to extract anything useful from it. Audacity gave some results but I don't think they are useful as when I zoom in there are too few digital steps to reliably see the frequencies properly. Is this meant to be the track that starts with 4 chimes at once followed by each of the 12 bells from highest to lowest? That is the one that is needed but at a much higher volume. Anyway this is what came out, but may not be correct. There are 14 so 2 are either harmonics or 2 bells have an extra resonant mode unrelated to the main one. 3487 2680 2375 2140 2016 1899 1803 1607 1487 1403 1349 1240 1080 . Edited 2025-11-13 16:18 by phil99 Footnote added 2025-11-13 16:24 by phil99 I missed one. the first 3 are 3487, 3187, 2680 |
||||
TassyJim![]() Guru Joined: 07/08/2011 Location: AustraliaPosts: 6363 |
I agree that the signal level was way too low. I started by amplifying it by 20dB but there is still the background noise to contend with. Most of the tones I detected were in the 30-40% high but it is promising to see so many agreeing with each other. There are also two phantom tones in my list. Jim VK7JH MMedit |
||||
| Frank N. Furter Guru Joined: 28/05/2012 Location: GermanyPosts: 997 |
Please excuse the poor sound quality! I will try again tomorrow with a different recorder. Frank |
||||
| Volhout Guru Joined: 05/03/2018 Location: NetherlandsPosts: 5476 |
Frank, In case you have a picomite VGA, you can analyze the audio yourself. Connect the audio signal to GP26(*) on the picomite VGA, and run below (very elementary) spectrum analyzer. 'GP26 audio spectrum analyzer VGA 'ping-pong ADC and calculate RMS value and fft 'runs on picomite VGA in mode 1 (640x480 monochrome) framebuffer create framebuffer write f 'system parameters Option base 1 n=512 'samples Dim a(n),b(n) 'ping pong buffers Dim c(n),d(n) 'processing buffer 'hardware parameters offset = -1.66 'hardware default freq = 10000 'ADC sampling frequency 'test signal generated from PWM 'SetPin gp0,pwm 'PWM 0,50,50 '50Hz, 50% d.c. 'test signal from audio output play tone 2000,1000 'open the ADC and start first conversion 'SetPin gp26,ain ADC OPEN freq,1,INT_RDY ready=0:pingpong=1 ADC START a() 'main routine Do 'every n/freq a new buffer is filled with samples and ready flag raised 'we have time to process the data. Using math commands we gain time 'rms is 4ms/512 samples, fft = 44ms/512 samples, plotting the graph consumes most time text 0,0,str$(timer,3,0) timer=0 If ready Then If pingpong Then MATH ADD b(),offset,c() Else MATH ADD a(),offset,c() EndIf rms = Math(SD c()) 'math(sd a()) does all the math to 'calculate rms from an array text 480,0,"RMS = "+str$(rms*scale,1,4) ready=0 'fft calculate magnitude MATH FFT MAGNITUDE c(),d() dummy=math(max d(),p%) 'determin what cell in the array has the highest value inc p%,-1 'because option bas 1 if p%>n/2 then p%=n-p% 'copy frequency mirror bin text 200,0,"Peak freq = "+str$(p%*freq/n,5,0)+" Hz" scale=(MM.VRES-10)/n MATH SCALE d(),scale,d() 'scale to match samples on 470 vertical 'resolution 'fft spectrum show bars=n/2-1:wdth=Int(MM.HRES/bars) For i=2 To bars'n/2 - 1 BOX i*wdth,470-d(i),wdth,d(i) Next i EndIf framebuffer copy f,n CLS Loop While Inkey$="" Save compressed image "fft_bars.bmp" End 'interrupt routine Sub INT_RDY If pingpong Then ADC START b() Else ADC START a() EndIf pingpong=1-pingpong ready=1 End Sub The screen will show the spectrum, the top right corner will show the level you input, try to increase the volume so get close to 1Vrms. Not higher, since you overdrive the input ADC. The sampler works at 10kHz, so you should be able to detect all frequencies up to 5kHz. ![]() This is the input circuit I used. ![]() Volhout P.S. the audio analyzer loop time is 70ms, so it most likely is fast enough to detect all notes (200ms between bells). P.P.S. for the purists: the display routine and FFT are much slower than the ADC sample engine, so there is more data acquired than is shown (roughly 40% more). Edited 2025-11-13 21:04 by Volhout PicomiteVGA PETSCII ROBOTS |
||||
| Frank N. Furter Guru Joined: 28/05/2012 Location: GermanyPosts: 997 |
That's very cool!!! I'll try that this weekend.That will also help me a lot in making the sound bodies. Frank |
||||
| twofingers Guru Joined: 02/06/2014 Location: GermanyPosts: 1681 |
Hi Frank, First off: I like Harm's program. I had planned something similar, but not by directly reading the voltage values, rather by reading them from a WAV file. I had assumed your bells were magnetically activated. However, I've seen fake bells online with an additional speaker. In that case, we obviously don't necessarily need a WAV file. Could you clarify that with a description and also explain what you're aiming for, what exactly you're planning? Kind regards Michael causality ≠ correlation ≠ coincidence |
||||
| Frank N. Furter Guru Joined: 28/05/2012 Location: GermanyPosts: 997 |
Michael, on the one hand, I'm afraid that the µC will die at some point and then my glockenspiel would become useless. On the other hand, I would like to recreate it with mechanical bells or sound elements. That means probably with sound tubes like in the link from Volhout on the first page of this thread. Controlling the bells correctly would already work now – so the first point no longer worries me... Yes, the bells on my glockenspiel are struck by electromagnets. I would just use an MP3 player then – that would be ugly. I want to build it in exactly the same way as my original, using electromechanical components. Playback via the Picomite sound output is only used to avoid errors. Frank P.S.: That would definitely be very useful! Edited 2025-11-13 23:33 by Frank N. Furter |
||||
| twofingers Guru Joined: 02/06/2014 Location: GermanyPosts: 1681 |
Hi Frank, all right! Then I don't understand how you plan to use Harm's program. Your microcomputer only gives you on/off values. Please don't misunderstand, this isn't a criticism of Harm's program! I imagine it would be useful if it used an amplified microphone signal as input. causality ≠ correlation ≠ coincidence |
||||
| Frank N. Furter Guru Joined: 28/05/2012 Location: GermanyPosts: 997 |
Michael, First of all, it's about finding the right bell frequencies (unless you're faster at it ) and then creating sound elements. To do this, I will have to measure the individual sound elements and, if necessary, adjust their length until the desired tone is achieved.Frank |
||||
| Volhout Guru Joined: 05/03/2018 Location: NetherlandsPosts: 5476 |
Update to the spectrum analyzer for pico VGA. ![]() GP26_audio_analyzer_VGA_2.zip Volhout PicomiteVGA PETSCII ROBOTS |
||||
| twofingers Guru Joined: 02/06/2014 Location: GermanyPosts: 1681 |
As I said, this is how I would proceed: Number the bells. Connect a microphone to the PC, start a recording program (in my case it would be Cooledit 2000), and ring each bell individually with a fixed object (a mallet) corresponding to the numbered bell – with short pauses in between. Check if the signal level is high enough. Then save everything as an MP3 file. Compress it as a ZIP archive and upload it here. @Harm, looks really good! Thanks! ![]() causality ≠ correlation ≠ coincidence |
||||
| Mixtel90 Guru Joined: 05/10/2019 Location: United KingdomPosts: 8296 |
Are you trying to imitate the bells or get the notes correct? It's quite possible that the bells aren't tuned to any particular scale, just done by someone's ear. Their notes may be produced with digital accuracy, but only relative to each other as the master oscillator could be a temperature-dependent RC network. It wouldn't matter in real life as they are unlikely to be played along with other instruments. If you want to get the notes correct then find a common tune that they play, then find the musical score for that tune. It will tell you the notes precisely. You can then use Volhout's table to get the exact frequencies that you need to produce for each note. The common Christmas tunes can be found all over the place. Another way. Use a Pico PLAY TONE to produce a C note. Then compare it with the bells to find one that sounds closest. Volhout's table will then give you the frequencies of the surrounding bells as they will be a 12-note scale. C may or may not be in the middle. . Edited 2025-11-14 01:20 by Mixtel90 Mick Zilog Inside! nascom.info for Nascom & Gemini Preliminary MMBasic docs & my PCB designs |
||||
| Volhout Guru Joined: 05/03/2018 Location: NetherlandsPosts: 5476 |
Hi mick, Your suggestion was Franks plan B. My VGA spectrum analyzer is plan F. Soo many plans. Volhout PicomiteVGA PETSCII ROBOTS |
||||
| Mixtel90 Guru Joined: 05/10/2019 Location: United KingdomPosts: 8296 |
Good job I didn't read everything then. :) Mick Zilog Inside! nascom.info for Nascom & Gemini Preliminary MMBasic docs & my PCB designs |
||||
| phil99 Guru Joined: 11/02/2018 Location: AustraliaPosts: 2828 |
So far the main issue in getting the frequencies is getting a noise free recording with enough amplitude. Several of us have used PC based analyzers but the current recordings are difficult to read. The Pico based analyzers will have the same issue. How were the bells arranged for the recording? If they are resting on anything the tone and loudness may be affected. I think suspending them in a tight circle around the microphone might give better results. Audacity for example can read the frequencies required for constructing a mechanical playback but also the "envelope" of each bell for the synthesized playback option. But as Frank said, that would be little different to a MP3 player. |
||||
TassyJim![]() Guru Joined: 07/08/2011 Location: AustraliaPosts: 6363 |
To summarize the results from Phil's and my tests. We found 14 separate notes. Two more than the number of bells. With a less noisy recording, we could probably eliminate the phantom notes. The majority of the tones are half way between standard notes. Piano tone standard note key found 85 3520.0 Hz A 7 3487 84 3322.4 Hz G#7 3200 83 3136.0 Hz G 7 82 2960.0 Hz F#7 81 2793.8 Hz F 7 2680 80 2637.0 Hz E 7 79 2489.0 Hz D#7 2375 78 2349.3 Hz D 7 77 2217.5 Hz C#7 2140 76 2093.0 Hz C 7 2016 75 1975.5 Hz B 6 1899 74 1864.7 Hz A#6 1803 73 1760.0 Hz A 6 72 1661.2 Hz G#6 1607 71 1568.0 Hz G 6 1487 70 1480.0 Hz F#6 1403 69 1396.9 Hz F 6 1349 68 1318.5 Hz E 6 67 1244.5 Hz D#6 1240 66 1174.7 Hz D 6 65 1108.7 Hz C#6 1080 64 1046.5 Hz C 6 First column is the piano key number second column is the tones found in the recording finally the standard notes as a reference. The interval between notes was a consistent (considering electro-mechanical parts) 240mS or multiple of. I don't have a musical bone in my body so there may be errors in the descriptions Jim VK7JH MMedit |
||||
| Mixtel90 Guru Joined: 05/10/2019 Location: United KingdomPosts: 8296 |
The bells, being bells, may not be tuned to a normal key. They are probably close to the correct musical relationship to each other, but not tuned. The precise frequencies don't matter as they won't be played with other instruments. Get the sequences right first. here's an example: D G G A G-F# E - E We wish you a Merry Christmas, E A A B A-G F# - D We wish you a Merry Christmas, D B B ^C B-A G - E D D E - A F# G We wish you a Merry Christmas and a Happy New Year! D G - G G F# F# G F# E D Good tidings we bring to you and your kin; A B - A G ^D - ^D E E E - A F# G Good tidings for Christmas and a Happy New Year! The relationship between notes will always be the same. This example is in the key of G major, but the bells may be in anything. The "We" at the beginning will be the biggest (lowest note) bell. Count up from there to get the others: 1 D 2 D# 3 E 4 F 5 F# 6 G 7 G# 8 A 9 A# 10 B 11 C 12 ^D You often find that the last note of a song is the base note for the key that it is in, so G in this case as it's in G major. As I said, although these are shown as G major it may not be in concert pitch so you don't actually know the precise frequencies. However, if you start at D on a piano or similar the notes will be in the correct relationship, even if they don't correspond to what the bells sound like! This is perfectly playable on a xylophone, for example. It's just a case of getting the timing right. You can get that from the musical stave, which shows the relationship between the note lengths. Mick Zilog Inside! nascom.info for Nascom & Gemini Preliminary MMBasic docs & my PCB designs |
||||
| phil99 Guru Joined: 11/02/2018 Location: AustraliaPosts: 2828 |
As noted previously some solenoid pulses are longer than others. They appear in most, if not all tunes in the full recording. It could be that these are deliberate to get a louder chime. So I suggest an experiment to find out. Disconnect a bell solenoid from the player and hook it up to a Pico via a transistor (with 2.2kΩ base resistor and reverse biased diode from collector to +12V) to +12V and run a command line program to compare the loudness of the standard pulse duration with the longer one. Do :Pulse GP0, 35 :Pause 200 :Pulse GP0, 55 :Pause 200 :Loop ' "Xylophone player pulse filter.bas" OutputDim integer Bell.note, Note.prev Dim float Bell.time, Bell.prev, Ding, interval '15 'Add to, or subtract from pulse duration (mS) For n=0 To 11 SetPin MM.Info(pinno "GP"+Str$(n)),DOUT Next '*******Add your recorded file name here.************* 'Open "RecordBellsFrank.dat" For Input As #1 'Open "BellSample.dat" For Input As #1 Open "RemappedALL.dat" For Input As #1 Print "List of solenoid pulses that are greater than 40mS" Print "Pulse mS","Solenoid(s)",,"recorded time S" Do Input #1, Bell.time, Bell.note 'get the data If Bell.note Then Note.prev=Bell.note Ding=bell.time-Bell.prev If (Bell.note=0) And (Ding > 40) Then Print Ding, Note.prev, Bin$(Note.prev,12), Bell.time/1000 Bell.prev = Bell.time Loop Until Eof(#1) End List of solenoid pulses that are greater than 40mS Pulse mS Solenoid(s) recorded time S 134.7 3264 110011000000 0.260116 55.467 128 000010000000 2.628993 56.5 1024 010000000000 44.339032 53.961 64 000001000000 199.690203 60.181 1024 010000000000 234.761601 53.417 4 000000000100 265.160832 54.228 2048 100000000000 471.215816 54.272 2304 100100000000 687.591088 57.378 32 000000100000 732.344462 55.947 576 001001000000 774.17021 53.774 72 000001001000 809.217 54.222 1024 010000000000 837.960805 57.378 1024 010000000000 897.256997 55.912 2048 100000000000 933.399468 52.333 288 000100100000 973.86001 54.386 16 000000010000 1053.768813 54.298 288 000100100000 1086.714309 55.975 512 001000000000 1153.06176 56.077 160 000010100000 1184.831196 56.034 576 001001000000 1215.966319 54.52 2112 100001000000 1277.618936 54.563 256 000100000000 1308.651649 52.435 64 000001000000 1340.188582 56.166 72 000001001000 1401.284143 54.394 32 000000100000 1438.408004 54.563 8 000000001000 1487.414759 54.545 512 001000000000 1517.914275 54.46 64 000001000000 1611.356135 55.727 1280 010100000000 1669.557919 525.765 2564 101000000100 1698.23718 When you build your new version you will be using different solenoids so may need to experiment with pulse durations to get the same effect. The Xylophone player program can then be adapted to replace the original pulse times with your new times. Edit. Another version of the player to show the individual tracks and which pulses are longer than normal. To speed it up the 2 lines that do the actual playing in real time have been commented out. It uses the file "RemappedALL.dat". The time intervals shown are from the start of one pulse to the start of the next. eg for track 0 (bell test) the pulses are 35mS separated by 200mS so the interval is 235mS. ' "Xylophone player & analyser.bas" Dim integer n, Bell.note, track 'number of on/off transitions in the sequence Dim float Bell.time, Bell.prev, Pulse.change = -0 'Add to, or subtract from pulse duration (mS) Dim LP$ 'indicate pulses greater than 40mS For n=0 To 11 SetPin MM.Info(pinno "GP"+Str$(n)),DOUT Next '*******Add your recorded file name here.************* Open "RemappedALL.dat" For Input As #1 Print " Track 0 - Bell Test" Print "Input time",,"Solenoid(s)",, "interval", "Pulse length" Timer = 0 Do Input #1, Bell.time, Bell.note 'get the data If Bell.note Then Inc Bell.time, -Pulse.change 'adjust pulse duration ' Do While Timer < Bell.time : Loop 'wait for next note or pulse ' Port(gp0,12) = Bell.note 'start / end solenoid pulse If Bell.time-Bell.prev > 3000 Then Inc track Print :Print Print " Track";track,"====================================================" Print "Input time",,"Solenoid(s)",, "interval", "Pulse length" EndIf If Bell.note Then Print Bell.time,, Bin$(Bell.note,12),, Bell.time-Bell.prev, If Bell.note=0 And Bell.time-Bell.prev > 40 Then LP$ = "Long Pulse" 'indicate pulses greater than 40mS Else LP$ = "" EndIf If Bell.note=0 Then Print Bell.time-Bell.prev, LP$ If Bell.note Then Bell.prev = Bell.time If Bell.note=0 Then Ding.prev = Bell.time Loop Until Eof(#1) Port(gp0,12) = 0 End The minimum interval in each track (tempo I guess). Track Tempo mS Tempo beats/S (approx.) 0 235 4.2 Bell test track 1 157 6.4 2 273 4.5 3 234 4.3 4 204 4.9 5 204 4.9 6 204 4.9 7 233 4.3 8 234 4.3 9 204 4.9 10 233 4.3 11 233 4.3 12 204 4.9 13 298 3.4 14 204 4.9 15 233 4.3 16 233 4.3 17 233 4.3 18 204 4.9 19 233 4.3 20 272 3.4 21 204 4.9 22 234 4.3 23 234 4.3 - another bell test track 24 156 6.4 Edited 2025-11-15 21:27 by phil99 |
||||
| The Back Shed's forum code is written, and hosted, in Australia. | © JAQ Software 2025 |