Sign in to follow this  
Followers 0
barbossa

ABX test for audio

1 post in this topic

This is a simple implementation of an ABX Test for audio files. In short, you get the same audio file encoded with different bitrates/methods/codecs to check if you can spot differences between them. I tried to find some Windows software to do this (to check how good is my hearing/new headphones), but couldn't find any, so I made one myself :oops:

Features include:

- support for all audio formats supported by your system ;-)

- simple seek bar

- (poorly) synched samples

If you find any bugs, corrections or suggestions, please let me know.

Here is the code:

#Region declarations
#NoTrayIcon
#include <Sound.au3>
#include <EditConstants.au3>
#include <ButtonConstants.au3>
#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>
#include <GUIEdit.au3>
#Include <GuiSlider.au3>
;options
Opt("GUIOnEventMode", 1)
;state variables
Dim $GUIShowing = 0
Dim $bFileAValid = False
Dim $bFileBValid = False
Dim $fileAPath
Dim $fileBPath
Dim $fileAHandle
Dim $fileBHandle
Dim $fileXHandle
Dim $playingFile = 0
Dim $numTests = 0
Dim $testHistory[51][2];50 tests, 0 is real X, 1 is guessed X
;definitions for setup GUI
Dim $GUIMain = GUICreate ("ABX test setup", 640, 140)
Dim $inputFileA = GUICtrlCreateInput("File A", 20, 20, 500, Default, 0x0800)
Dim $buttonOpenFileA = GUICtrlCreateButton ("Open...", 530, 20, 90, Default)
Dim $inputFileB = GUICtrlCreateInput("File B", 20, 60, 500, Default, 0x0800)
Dim $buttonOpenFileB = GUICtrlCreateButton ("Open...", 530, 60, 90, Default)
Dim $labelFileAOK = GUICtrlCreateLabel ("File A invalid", 20, 100, 100, Default)
Dim $labelFileBOK = GUICtrlCreateLabel ("File B invalid", 120, 100, 100, Default)
Dim $buttonStart = GUICtrlCreateButton ("Start test", 520, 100, 100, Default)
Dim $buttonAbout = GUICtrlCreateButton ("About...", 400, 100, 100, Default)
GUICtrlSetOnEvent ($buttonOpenFileA, "OpenFileA")
GUICtrlSetOnEvent ($buttonOpenFileB, "OpenFileB")
GuiCtrlSetOnEvent ($buttonStart, "StartTest")
GuiCtrlSetOnEvent ($buttonAbout, "AboutBox")
GUISetOnEvent($GUI_EVENT_CLOSE, "CLOSEClicked")
Dim $GUITest = GUICreate ("ABX test", 260, 300)
Dim $soundPosition = GUICtrlCreateSlider(16, 112, 225, 33)
Dim $buttonPlayA = GUICtrlCreateButton("Play A", 16, 32, 65, 65)
Dim $buttonPlayB = GUICtrlCreateButton("Play B", 96, 32, 65, 65)
Dim $buttonPlayX = GUICtrlCreateButton("Play X", 176, 32, 65, 65)
Dim $labelTestNumber = GUICtrlCreateLabel("Test Number:", 16, 8, 68, 17)
Dim $buttonXisA = GUICtrlCreateButton("X is A", 56, 152, 65, 65)
Dim $buttonXisB = GUICtrlCreateButton("X is B", 136, 152, 65, 65)
Dim $buttonStopSound = GUICtrlCreateButton("STOP SOUND", 16, 216, 225, 33)
Dim $buttonEndTest = GUICtrlCreateButton("END TEST", 16, 256, 225, 33)
GUICtrlSetOnEvent ($buttonPlayA, "PlayA")
GUICtrlSetOnEvent ($buttonPlayB, "PlayB")
GUICtrlSetOnEvent ($buttonPlayX, "PlayX")
GuiCtrlSetOnEvent ($soundPosition, "SeekSound")
GuiCtrlSetOnEvent ($buttonStopSound, "StopSound")
GuiCtrlSetOnEvent ($buttonEndTest, "EndTests")
GuiCtrlSetOnEvent ($buttonXisA, "XisA")
GuiCtrlSetOnEvent ($buttonXisB, "XisB")
GuiCtrlSetOnEvent ($buttonEndTest, "EndTests")
GUISetOnEvent($GUI_EVENT_CLOSE, "CLOSEClicked")
Dim $GUIresults = GUICreate("Test results", 330, 440)
Dim $textResults = GUICtrlCreateEdit("", 8, 8, 313, 417, BitOR($GUI_SS_DEFAULT_EDIT,$ES_READONLY))
GUISetOnEvent($GUI_EVENT_CLOSE, "CLOSEClicked")
#endregion declarations

#region Main Loop
GUISwitch($GUIMain)
GUISetState(@SW_SHOW)
While True
Sleep (1000)
Switch $GUIShowing
  Case 0
   If $bFileAValid Then
    GUICtrlSetData($labelFileAOK, "File A VALID")
   Else
    GUICtrlSetData($labelFileAOK, "File A invalid")
   EndIf
   If $bFileBValid Then
    GUICtrlSetData($labelFileBOK, "File B VALID")
   Else
    GUICtrlSetData($labelFileBOK, "File B invalid")
   EndIf
  Case 1
   If _SoundStatus($playingFile) = "playing" Then
    GUICtrlSetData($soundPosition, Ceiling((_SoundPos($playingFile, 2) / _SoundLength($playingFile, 2)) * 100))
   EndIf
EndSwitch

WEnd
#endregion Main Loop
#region Functions
Func CLOSEClicked()
MsgBox(64, "Exit", "Exiting...", 2)
Exit
EndFunc
Func OpenFileA ()
$fileAPath = FileOpenDialog ("Audio file A", Default, "Audio Files (*.mp3;*.wav;*.flac)", 3)
If @error <> 1 Then
  _GUICtrlEdit_SetText($inputFileA, $fileAPath)
  $fileAHandle = _SoundOpen($fileAPath)
  If @error <> 0 Then
   MsgBox(16, "Error", "Error loading the file.", 0, $GUIMain)
   $bFileAValid = False
  Else
   MsgBox(64, "OK", "File loaded successfully.", 0, $GUIMain)
   $bFileAValid = True
  EndIf
Else
  MsgBox(16, "Error", "Error opening the file.", 0, $GUIMain)
EndIf
EndFunc
Func OpenFileB ()
$fileBPath = FileOpenDialog ("Audio file B", Default, "Audio Files (*.mp3;*.wav;*.flac)", 3)
If @error <> 1 Then
  _GUICtrlEdit_SetText($inputFileB, $fileBPath)
  $fileBHandle = _SoundOpen($fileBPath)
  If @error <> 0 Then
   MsgBox(16, "Error", "Error loading the file.", 0, $GUIMain)
   $bFileBValid = False
  Else
   MsgBox(64, "OK", "File loaded successfully.", 0, $GUIMain)
   $bFileBValid = True
  EndIf
Else
  MsgBox(16, "Error", "Error opening the file.", 0, $GUIMain)
EndIf
EndFunc
Func StartTest ()
If $bFileAValid And $bFileBValid Then
  GUISetState(@SW_HIDE)
  GUISwitch($GUITest)
  GUISetState(@SW_SHOW)
  $GUIShowing = 1
  NewTest()
Else
  MsgBox (16, "Error", "Both files must be valid.", 0, $GUIMain)
EndIf
EndFunc
Func PlayA ()
_SoundPause($playingFile)
$playingFile = $fileAHandle
SeekSound ()
EndFunc
Func PlayB ()
_SoundPause($playingFile)
$playingFile = $fileBHandle
SeekSound ()
EndFunc
Func PlayX ()
_SoundPause($playingFile)
$playingFile = $fileXHandle
SeekSound ()
EndFunc
Func SeekSound ()
Dim $hour, $minute, $second
Dim $percent
Dim $time_in_seconds
$percent = _GUICtrlSlider_GetPos($soundPosition)
$time_in_seconds = Floor((_SoundLength($playingFile, 2) / 1000) * ($percent / 100))
$hour = Floor($time_in_seconds/3600)
$time_in_seconds = Mod($time_in_seconds, 3600)
$minute = Floor($time_in_seconds/60)
$time_in_seconds = Mod($time_in_seconds, 60)
$second = $time_in_seconds
_SoundSeek($playingFile, $hour, $minute, $second)
_SoundPLay($playingFile)
EndFunc
Func StopSound ()
_SoundStop($playingFile)
EndFunc
Func XisA ()
$testHistory[$numTests][1] = "A"
NewTest()
EndFunc
Func XisB ()
$testHistory[$numTests][1] = "B"
NewTest()
EndFunc
Func AboutBox ()
MsgBox(0, "About ABX tester", _
"Implement ABX double blind test for different quality settings audio files." & @CRLF & _
"The test consists of a number of trials in wich the test subject must listen" & @CRLF & _
"to two audio samples (A and B) and compare them to one of them, randomly" & @CRLF & _
"assigned to X. For a minimum of 16 tests, if the subject chooses the correct" & @CRLF & _
"file less than 95% of the time, then the null hypothesis (there is no signi-" & @CRLF & _
"ficant difference between A and B) cannot be rejected." & @CRLF & _
"" _
, 0, $GUIMain)
EndFunc
Func EndTests()
Dim $i
Dim $totalRight = 0
Dim $tmpData
GUISetState(@SW_HIDE)
GUISwitch($GUIresults)
GUISetState(@SW_SHOW)
$GUIShowing = 2
For $i = 1 to $numTests
  If $testHistory[$i][1] <> "" Then
   $tmpData = $tmpData & "Test " & StringFormat("%02d", $i) & ": X was " & _
        $testHistory[$i][0] & ", your answer was " & _
        $testHistory[$i][1] & @CRLF
   If $testHistory[$i][0] = $testHistory[$i][1] Then
    $totalRight += 1
   EndIf
  EndIf
Next
$tmpData = $tmpData & "Total right: " & $totalRight & " (" & Round(($totalRight/$numTests)*100, 2) & "%)"
GuiCtrlSetData($textResults, $tmpData)
EndFunc
;randomly assigns file A or B to X
Func SetFileX ()
Dim $i
$i = Random (1, 2, 1)
If $i = 1 Then
  $fileXHandle = $fileAHandle
  $testHistory[$numTests][0] = "A"
Else
  $fileXHandle = $fileBHandle
  $testHistory[$numTests][0] = "B"
EndIf
EndFunc
Func NewTest ()
If $numTests < 50 Then
  $numTests += 1
  MsgBox(64, "Setting X", "Test " & $numTests & @CRLF & "setting file X...", 2, $GUITest)
  SetFileX()
  GUICtrlSetData($labelTestNumber, $numTests)
  StopSound()
Else
  EndTests()
EndIf
EndFunc
#endregion Functions

Share this post


Link to post
Share on other sites



Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0