Impulse Response Measurement Using a NI USB-4431 Device
This example shows how to measure an impulse response using a National Instruments (NI) USB-4431 sound and vibration device. You set up the device, create an excitation signal to play, and simultaneously record the response. Finally, you compute the response from the recording and plot the results.
For this example, you need Audio Toolbox™ and Data Acquisition Toolbox™. You also need to have installed the NI drivers (recommended) or the MATLAB NI support package.
Verify if the NI USB-4431 is connected and the proper drivers are installed using the
ans=1×4 table DeviceID Description Model DeviceInfo ________ ___________________________________ __________ ________________________________________ "Dev1" "National Instruments(TM) USB-4431" "USB-4431" 1×1 daq.ni.DeviceSpecializations.USB4431
Next, knowing that this device only supports clocked operations, you can disable the warning.
ws = warning("off","daq:Session:clockedOnlyChannelsAdded"); % restore warning state when cleared oc = onCleanup(@() warning(ws));
Setup the NI device with a sampling rate of 48 kHz, one input, and one output.
To do so, create a
daq object for NI devices and set
Rate to 48 kHz.
FS = 48e3; dq = daq("ni"); dq.Rate = FS; dev = "Dev1";
Add one input and one output. In this example, the microphone has its own pre-amplifier, so set the measurement type to
Voltage. The output is connected to a powered loudspeaker and the measurement type is set to
Create an exponential swept sine going from 20 Hz to 24 kHz over a period of 3 seconds, followed by one second of silence. This limits the maximum impulse response length to one second. You can also set the output level, in this case -18 dB.
irDur = 1; sweepDur = 3; outputLevel = -18; sweepRange = [20 24000]; exc = sweeptone( ... sweepDur, irDur, FS, ... ExcitationLevel=outputLevel, ... SweepFrequencyRange=sweepRange);
readwrite method of the
daq object (
dq), play the swept sine stimulus (
exc) and simultaneously record the response.
data = readwrite(dq,exc); dq = ; % release
Compute the Impulse Response
impzest function to compute the impulse response (
ir) from the stimulus (
exc) and its response.
response = data.Variables; ir = impzest(exc,response);
Create the corresponding time vector.
t_sec = (0:length(ir)-1).'/FS;
Display the Results
Plot the first 10 milliseconds, in this case, 480 samples.
totalDur = sweepDur*FS; n = 480; plot(t_sec(1:n), ir(1:n)) title("Impulse Response") ylabel("Amplitude") xlabel("Time (s)") grid on
Impulse Response Measurer App
Another way of writing the code above is to start from a script generated from the Impulse Response Measurer app. Start the app by entering
impulseResponseMeasurer at the command prompt. You can also click the app icon on the Apps tab of the MATLAB® Toolstrip. Even without a supported device connected, you can set the Method Settings, Display Settings and a linear or log scale for magnitude and phase responses (using the toolbar that appears when hovering the mouse over these plots). Then, click Generate Script. A new document will appear in the editor with code for an audio device, that you will modify to use the NI USB-4431.
First, you may want to make this a function by adding
function capture = irm_usb4431 to the top of the file, and an
end statement before the first embedded function.
The function to interface with the NI device can take a complete signal, without proceeding frame by frame. Consequently, remove the code for "
Allocate the input/output buffers" and "
Copy the excitation to the output buffer".
The code required to "
Setup the audio device" can be replaced by code to setup the NI USB-4431 device. Set the sample rate of the device and add an output and at least one input.
dq = daq("ni"); dq.Rate = 48e3; % Sampling rate addinput(dq,"Dev1","ai0","Voltage"); addoutput(dq,"Dev1","ao0","Voltage");
The playback and capture loop can be replaced by a
readwrite statement. Get the results from
data.Variables instead of the buffer. Also get the handle from the first figure to facilitate zooming in.
Now run the customized function
irm_usb4431 to obtain the capture data and plot the results and zoom in.
[capture,ax1] = irm_usb4431(); xlim(ax1,[0 10e-3]);
The data is also available programmatically.
capture = struct with fields: ImpulseResponse: [1×1 struct] MagnitudeResponse: [1×1 struct] PhaseResponse: [1×1 struct]
For example, plot the first 480 samples of the impulse response.
figure % new figure plot(capture.ImpulseResponse.Time(1:480), capture.ImpulseResponse.Amplitude(1:480)) title("Impulse Response") ylabel("Amplitude") xlabel("Time (s)") grid on