• WANTED: Happy members who like to discuss audio and other topics related to our interest. Desire to learn and share knowledge of science required. There are many reviews of audio hardware and expert members to help answer your questions. Click here to have your audio equipment measured for free!

3d measurement set up for guitars /loudsepakers

Jenser17

New Member
Joined
Oct 4, 2024
Messages
4
Likes
7
Location
Lower Saxony Germany
Dear all. I am new to this forum and want to share and ask for help of the software side.
I am working in the audio automotive world and in my free time I build guitars.
As I want to understand the acoustics of there’s instruments there is no way other then to measure the Impuls responses.
Lots of work has been done by Meyer and Schleske and others.
But without acces to raw data and being able to measure my own instruments I feel blind

So I spent some time working on a mics array consisting of mini esp UmikX mems and a turntable and a controlled Impuls hammer to tap the instrument.
1350F2C8-73D8-4B4D-BD8B-2419D038D9FA.jpeg

This all works fine it’s controlled by an ardurino and I can record the impulses responses.

But the recording and naming of the files is a pain. I read the Klippen Scanner diy posts and love it. Thanks a lot for sharing. Does anybody know a software solution or can help me out finding a tool that can record 12 mic channels at a time and calculate the Impuls response by usage of the hammer signal and rename and safe the files in the needed order so it can be shown as balloon plots?

If you l want to know what I do and build https://www.instagram.com/jens_feldhaus?igsh=aGJwbGVieWJyMGVh&utm_source=qr


Thanks a lot for your help and I am happy to discuss and share hammer and turntable info.

Cheers Jens
 
Very cool setup!

This just screams for a Python script, you could automate the whole thing! How do you communicate with the Arduino from your recording computer?
 
I have the ardurino action controlled by several buttons. for postioning the hit point and hitting, and turning 15 degrees and also an automated mode, where the hammer taps and moves and taps and moves.
The ardurino is used as stand alone version, no control of it via PC right now.

I have to admit, i did not pay interest in my coding lessons a university, spent all time in the recording studio was more fun to me then... :( So I am not able to programm some python code..

As long as REW is not capable of recording impuls resonses by an impact hammer, I am sticked to record the time signal in nuendo and then cut all impuls responses, name those and find a way to bring into vituix or Vacs.

If you know of any pyhon project that could be maye reused or expanded, it would be a big help.

I have some measurement reports of some guitars I built in comparison with some old Gibson, measured an older set up, I will add it here.
 

Attachments

  • Feldhaus Sound Works 17 inch Cello Archtop Analysis (4).pdf
    1.8 MB · Views: 73
I think a reasonable end goal is to have everything automated, the spinning, hammering, recording and fft'ing. But one step at a time, right! I made some quick, untested scripts based on the example here. If you can get Python running and the dependencies installed we can take it from there. I assume you're on Windows? I don't use it, but I hear Anaconda is a good way to install Python on Windows.

import argparse
import pathlib

import sounddevice as sd
import scipy.io.wavfile


def int_or_str(text):
"""Helper function for argument parsing."""
try:
return int(text)
except ValueError:
return text

parser = argparse.ArgumentParser(add_help=False)
parser.add_argument(
'-l', '--list-devices', action='store_true',
help='show list of audio devices and exit')
args, remaining = parser.parse_known_args()
if args.list_devices:
print(sd.query_devices())
parser.exit(0)

parser = argparse.ArgumentParser(
description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter,
parents=[parser])
parser.add_argument(
'id',
help='id to prepend to channel filenames')
parser.add_argument(
'-d', '--device', type=int_or_str,
help='output device (numeric ID or substring)')
parser.add_argument(
'-r', '--samplerate', type=int, default=96000, help='sampling rate')
parser.add_argument(
'-c', '--channels', type=int, default=1, help='number of input channels')
parser.add_argument(
'-s', '--seconds', type=int, default=5, help='number of seconds to record')


args = parser.parse_args(remaining)

fs = args.samplerate

pathlib.Path("record").mkdir(exist_ok=True)

rec = sd.rec(int(args.seconds * fs), samplerate=fs, channels=args.channels, device=args.device)
sd.wait() # Wait until recording is finished

for ch in range(rec.shape[1]):
scipy.io.wavfile.write(f"record/{args.id}-{ch:02}.wav", fs, rec[:,ch])

import pathlib

import matplotlib.pyplot as plt
import numpy as np
import scipy


record_dir = pathlib.Path("record")
fft_dir = pathlib.Path("fft")

fft_dir.mkdir(exist_ok=True)

for filename in record_dir.glob("**/*.wav"):
fd, rec = scipy.io.wavfile.read(filename)
fft = scipy.fft.fft(rec)
freq = scipy.fft.fftfreq(rec.shape[0])
ax = plt.gca()
ax.cla()
ax.plot(freq, 20*np.log10(np.abs(fft)))

out_dir = fft_dir / filename.relative_to(record_dir).parent
out_dir.mkdir(exist_ok=True)

out_file = out_dir / filename.with_suffix(".png").name
ax.figure.savefig(out_file)

This is how you're supposed to use the scripts from the command line:

Find the correct device number:
python3 record.py -l

Use the device number from above, set the channels and recording time, and set an id based on the current angle:
python3 record.py --device 1 --channels 12 --seconds 5 0-deg
^right after starting this line, trigger the hammer

When the recording is done, run this command to create a bunch of fft plots in the fft folder:
python3 fft.py

Right now this just generates a bunch of image files, but if you can get this running we could move on to creating some more useful data.

(And if you don't want to bother with any of this that's completely fine, I did it for fun :))
 
And on a more theoretical level, one problem I see is that you pretty much have to include the room in the measurement. You can't really do time gating like you would on a speaker measurement, because there's a bunch of dynamics going on in the guitar that you need to capture. So if someone else built a similar measurement rig (me, for example), it would be difficult to compare the results.
 
And on a more theoretical level, one problem I see is that you pretty much have to include the room in the measurement. You can't really do time gating like you would on a speaker measurement, because there's a bunch of dynamics going on in the guitar that you need to capture. So if someone else built a similar measurement rig (me, for example), it would be difficult to compare the results.
Yes you are right about the room influence. The room is quite dampened (0.3 sec) above 100hz.
The low e string of this instrument is around 80 Hz. Maximal F I look into with this set up is 2 kHz. The hammer tip is medium hard to will only be valid up to 2kHz and the fundamental tones of the guitar are on a normal acoustic instrument are around 1.2kHz. Mostly all the overtones and higher stuff is emmited by the strings themself. These are damped in this set up. So capturing the first modes and some higher modes of the wooden body is the goal, as is the special dispersion of the instrument.
 
I think a reasonable end goal is to have everything automated, the spinning, hammering, recording and fft'ing. But one step at a time, right! I made some quick, untested scripts based on the example here. If you can get Python running and the dependencies installed we can take it from there. I assume you're on Windows? I don't use it, but I hear Anaconda is a good way to install Python on Windows.

import argparse
import pathlib

import sounddevice as sd
import scipy.io.wavfile


def int_or_str(text):
"""Helper function for argument parsing."""
try:
return int(text)
except ValueError:
return text

parser = argparse.ArgumentParser(add_help=False)
parser.add_argument(
'-l', '--list-devices', action='store_true',
help='show list of audio devices and exit')
args, remaining = parser.parse_known_args()
if args.list_devices:
print(sd.query_devices())
parser.exit(0)

parser = argparse.ArgumentParser(
description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter,
parents=[parser])
parser.add_argument(
'id',
help='id to prepend to channel filenames')
parser.add_argument(
'-d', '--device', type=int_or_str,
help='output device (numeric ID or substring)')
parser.add_argument(
'-r', '--samplerate', type=int, default=96000, help='sampling rate')
parser.add_argument(
'-c', '--channels', type=int, default=1, help='number of input channels')
parser.add_argument(
'-s', '--seconds', type=int, default=5, help='number of seconds to record')


args = parser.parse_args(remaining)

fs = args.samplerate

pathlib.Path("record").mkdir(exist_ok=True)

rec = sd.rec(int(args.seconds * fs), samplerate=fs, channels=args.channels, device=args.device)
sd.wait() # Wait until recording is finished

for ch in range(rec.shape[1]):
scipy.io.wavfile.write(f"record/{args.id}-{ch:02}.wav", fs, rec[:,ch])

import pathlib

import matplotlib.pyplot as plt
import numpy as np
import scipy


record_dir = pathlib.Path("record")
fft_dir = pathlib.Path("fft")

fft_dir.mkdir(exist_ok=True)

for filename in record_dir.glob("**/*.wav"):
fd, rec = scipy.io.wavfile.read(filename)
fft = scipy.fft.fft(rec)
freq = scipy.fft.fftfreq(rec.shape[0])
ax = plt.gca()
ax.cla()
ax.plot(freq, 20*np.log10(np.abs(fft)))

out_dir = fft_dir / filename.relative_to(record_dir).parent
out_dir.mkdir(exist_ok=True)

out_file = out_dir / filename.with_suffix(".png").name
ax.figure.savefig(out_file)

This is how you're supposed to use the scripts from the command line:

Find the correct device number:
python3 record.py -l

Use the device number from above, set the channels and recording time, and set an id based on the current angle:
python3 record.py --device 1 --channels 12 --seconds 5 0-deg
^right after starting this line, trigger the hammer

When the recording is done, run this command to create a bunch of fft plots in the fft folder:
python3 fft.py

Right now this just generates a bunch of image files, but if you can get this running we could move on to creating some more useful data.

(And if you don't want to bother with any of this that's completely fine, I did it for fun :))
Thanks a lot. I hope I have some time this weekend to look into it and try to get python running.
 
Back
Top Bottom