Best Digital (bit perfect) Test Signal?

This old topic is closed. If you want to reopen this topic, contact a moderator using the "Report Post" button.
I am planning on performing the following experiment to figure out how to prevent iTunes from tampering with the signal:

Motivation: I have read conflicting accounts of where the volume in iTunes should be set for bit perfect output (of the application), and even if it is possible at all.

Proposed Method: (all of this on mac os x)
1. Generate a short test signal in MATLAB, maybe a couple seconds long, and write it to disk as a .WAV file

2. Play the test signal in iTunes, using JACK to route it to an application that I am confident will do a bit perfect recording to disk, again to a .wav file or similarly lossless audio format, if necessary using Quicktime to convert to something MATLAB can read.

3. Write a MATLAB script to align the test signal as well as possible and determine if it matches the input signal perfectly.

If I get a bit perfect comparison, I can be confident that nothing messed with the signal along the chain, although if the signal gets messed up I won't immediately know which application to blame.

Expected Results:
I'm expecting iTunes to be bit perfect (with Sound Check and Equilizer turned off) with the application volume all the way up. I am guessing that the clipping some others have obeserved was introduced by the system-wide volume control and mixing. I have also heard indirect accounts that the volume control should be set halfway to avoid clipping. This corroborates the system-wide volume setting theory.

So, I'm posting to ask what the best test signal would be to use. It should have as many of the following desirable properties as possible.
1. Easy to align the original signal with the distorted signal in time, even with significant distortion.
2. Easy to generate.
3. Test every possible output level.
4. Not to sound too awful; i.e. sounding like white/pink noise would be good.
5. Not be likely to dammage any components, since it is inevitable someone will eventually play the test signal through their amp, speakers, etc. Specifically, unnaturally high support in the high frequencies can dammage tweeters, and I've read that a high DC offset can dammage headphones if the amp doesn't reject DC well.
6. Be deterministic and easy to code, so results are easy to duplicate in other programming languages and different file formats.

The best signal I can think of would be to randomly permute all 2^16 = 65, 536 levels in time, and then leave the output at mid-level for an equivalent amount of time. I would expect this to sound like a burst of white noise about once a second.

I think this should satisfy 1, 2, 3, 4, 5, but not 6 since it is not deterministic.

Anyone know of something better? Maybe a signal that would make synchronization easier, or maybe a nice pseudorandom way of generating the sequence of output levels?
iTunes application output is bit perfect!

iTunes is Bit Perfect. Here are the details of my experiment. Stay tuned for the scripts I used.


WARNING: Do NOT wear headphones during any part of this process. The test file is extremely loud, so turn the volume on your volume down before playing the test file. (i.e. the hardware knob on your amp, not any software knob or slider)

Make sure you are running Mac OS 10.3.9
Install MATLAB ( I'm at (R14) Service Pack 1, but this should not matter)
Install jackosx (not out for tiger at the time of writing)
Installed QuickTime 7, registered to Pro Version.

Run "generate_test_signal.m" to generate the file "test_signal.wav"

Start Jack

iTunes preferences settings:
Audio Pane -> Uncheck "Crossfade playback"
Audio Pane -> Uncheck "Sound Enhancer"
Audio Pane -> Uncheck "Sound Check"
Window Menu -> Equalizer -> Uncheck "On"

Quicktime Settings:
Recording Pane -> Microphone -> "Jack Router"
Recording Pane -> Quality -> "Device Native"

In Jack Router,
futz around with things until you get both quicktime player and itunes in the routing window. I can't remember the exact sequence, but I think you have to make sure Jack Router is the default input and default output device in System Preferences.

Turn off all routing by selecting each output in turn, and double-clicking all inputs it is connected to until nothing is highlighted in red. Route the output of iTunes into the "Built-in Audio" so you can hear what you're playing and recording. Also route the output of iTunes into Quicktime Player.

Start a new audio recording in Quicktime Player using File -> New Audio Recording

Open the test signal in iTunes and when you play, make sure the recording level is jumping up in the "Audio Recording" window. It should be almost maxed out.

Play the file from the beginning in iTunes.

In Quicktime,
Hit the record button in the recording window.
When the signal is done playing, hit stop in the recording window.

Use Filer -> "Show Movie Info" and note that since the data has passed through core audio it has been upgraded to 32 bit float.
Use File -> Export to "Export Sound to Wave" making sure to set the "Use" field to "44.1 kHz 16 bit Stereo"

Trim both the original and distorted files to contain a half cycle. i.e. zeros, noise, then zeros in the channel of your choice. You can do this by moving around the selection sliders, Selecting "Edit" -> "Trim to selection" and then exporting the files again to new filenames.

Run "compare_test_signals.m" on the trimmed files. If the files are identical up to a time translation, the the script will display "Bit Perfect output!".

When the above steps were taken with the iTunes volume set to full, bit perfect output from the iTunes application was obtained.

When the volume in iTunes was set to a half and the experiment was run again, bit perfect output from the application was not obtained.

Please do not exaggerate the importance of this. Since Apple's core audio is based on a 32 bit data type, my understanding is that even if you did have the slider set at volume less than full, and as long as you don't saturate the signal somewhere else in the audio chain, the difference would be practically impossible to discern.

This is primarily of interest to people who are trying to build an audio system that is as good as they can possibly make it, and who don't want to have to even consider the possibility of loss of signal quality due to numerical precision problems in the computer. They generally want digital signal to make it from the CD to their hard drive to their DAC of choice completely unaltered.

Enjoy your music and sleep tight knowing your bits are safe!

Drew Wagner
MATLAB script for generating the test signal.

% generate_test_signal.m
% Generate a test signal to facilitate testing if iTunes is bit perfect.
% The larger goal is to figure out what volume level to set iTunes at (if any) for bit-perfect audio.

clc; clear

% Generate a test signal.

levelCount = 2^BITS_PER_CHANNEL;

temp1 = randperm(levelCount)' - 1; % A vector of integer values in [0, levelCount), stored in MATLAB float.
temp1 = temp1 ./ levelCount * 2; % A vector of values in [0, 2);
temp1 = temp1 - 1; % A vector of values in [-1, 1). This should be exact, at least for the GNU octave wavwrite.

temp2 = [temp1 zeros(size(temp1)); zeros(size(temp1)) temp1]; % Left Channel first, then right channel.
clear temp1;

temp3 = [temp2; temp2; temp2];
clear temp2;

%auwrite(temp3,SAMPLE_FREQUENCY,BITS_PER_CHANNEL,'linear', '');
wavwrite(temp3, SAMPLE_FREQUENCY, BITS_PER_CHANNEL, 'test_signal.wav');

MATLAB script for comparing trimmed test signals.

% compare_test_signals.m
% Load two signals from the disk that have a certain format and compare them.
clc; clear;

%file1 = 'test_signal_trimmed.wav';
%file2 = 'test_signal_distorted_trimmed.wav';

file1 = 'test_signal_trimmed.wav';
file2 = 'test_signal_half_volume_trimmed.wav';


disp('Loading the two files...')
signal1 = wavread(file1);
signal2 = wavread(file2);


% Pull out the channel of our choice from each channel.
% Also turn into row vectors so easier to deal with.
disp('Keeping the first channel...')
signal1 = signal1:),1);
signal2 = signal2:),1);

% Trim the zeros from the beginning and end of the first signal.
temp1 = find(signal1 ~= 0);
temp2 = temp1(1); % This is the index of the first non-zero value.
if(temp2 < 20),
disp('It seems that the first signal does not start with zeros!');
temp3 = temp1(end); % This is the index of the last non-zero value.
if(temp3 > length(signal1) - 20),
disp('It seems that the first signal does not end with zeros!');
signal1 = signal1(temp2:temp3);

% Trim the zeros from the beginning and end of the second signal.
temp1 = find(signal2 ~= 0);
temp2 = temp1(1); % This is the index of the first non-zero value.
if(temp2 < 20),
disp('It seems that the second signal does not start with zeros!');
temp3 = temp1(end); % This is the index of the last non-zero value.
if(temp3 > length(signal2) - 20),
disp('It seems that the second signal does not end with zeros!');
signal2 = signal2(temp2:temp3);

% Compare the two signals
if(~any(signal1 - signal2)),
disp('Bit Perfect output!');
disp('Output is not bit perfect!')
This old topic is closed. If you want to reopen this topic, contact a moderator using the "Report Post" button.