Posted: 02:23am 13 Nov 2025 Copy link to clipboard
twofingers Guru
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
Posted: 02:42am 13 Nov 2025 Copy link to clipboard
TassyJim Guru
My version of CoolEdit using waterfall display
Frequencies detected (first number is time from start):
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
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
Posted: 05:57am 13 Nov 2025 Copy link to clipboard
phil99 Guru
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
Posted: 06:14am 13 Nov 2025 Copy link to clipboard
TassyJim Guru
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
Posted: 07:49am 13 Nov 2025 Copy link to clipboard
Frank N. Furter Guru
Please excuse the poor sound quality!
I will try again tomorrow with a different recorder.
Frank
Posted: 10:25am 13 Nov 2025 Copy link to clipboard
Volhout Guru
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
'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
Posted: 11:37am 13 Nov 2025 Copy link to clipboard
Frank N. Furter Guru
That's very cool!!! I'll try that this weekend. That will also help me a lot in making the sound bodies.
Frank
Posted: 12:45pm 13 Nov 2025 Copy link to clipboard
twofingers Guru
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
Posted: 01:28pm 13 Nov 2025 Copy link to clipboard
Frank N. Furter Guru
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
Posted: 01:51pm 13 Nov 2025 Copy link to clipboard
twofingers Guru
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.
Posted: 01:58pm 13 Nov 2025 Copy link to clipboard
Frank N. Furter Guru
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
Posted: 02:28pm 13 Nov 2025 Copy link to clipboard
Posted: 03:00pm 13 Nov 2025 Copy link to clipboard
twofingers Guru
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!
Posted: 03:17pm 13 Nov 2025 Copy link to clipboard
Mixtel90 Guru
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
Posted: 03:53pm 13 Nov 2025 Copy link to clipboard
Volhout Guru
Hi mick,
Your suggestion was Franks plan B. My VGA spectrum analyzer is plan F. Soo many plans.
Volhout
Posted: 06:51pm 13 Nov 2025 Copy link to clipboard
Mixtel90 Guru
Good job I didn't read everything then. :)
Posted: 09:08pm 13 Nov 2025 Copy link to clipboard
phil99 Guru
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.
Posted: 06:42am 14 Nov 2025 Copy link to clipboard
TassyJim Guru
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
Posted: 09:17am 14 Nov 2025 Copy link to clipboard
Mixtel90 Guru
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.
Posted: 12:45am 15 Nov 2025 Copy link to clipboard
phil99 Guru
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.
' "Xylophone player pulse filter.bas" Dim 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 Print "List of solenoid pulses that are greater than 40mS" Print Print "Pulse mS","Solenoid(s)",,"recorded time S" Print
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) Print End
Output
List of solenoid pulses that are greater than 40mS
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 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" Print 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).