That's very similar to what I'm doing, but not using system.util.globals (maybe I should be?)
I have a tag named BasePath that stores the base file path on the server C:\SCADA in your instance, then I have a few gateway message handlers in my gateway scripting project as follows:
GetAlarmSoundList
def handleMessage(payload):
	import os
	import errno
	
	folderPath = system.tag.readBlocking('BasePath')[0].value + '\AlarmSounds'
	try:
		os.makedirs(folderPath)
	except OSError as e:
		if errno.EEXIST != e.errno:
			raise
			
	fileList = []
	files = os.listdir(folderPath)
	for fileName in files:
		if fileName.upper().endswith('.WAV'):
			fileList.append(fileName)
			
	return fileList
GetAlarmSound
def handleMessage(payload):
	if payload['fileName']:
		filePath = system.tag.readBlocking('BasePath')[0].value + '\AlarmSounds\%s' % payload['fileName']
		if system.file.fileExists(filePath):
			bytes = system.file.readFileAsBytes(filePath)
			return bytes
On my project, I have a library:
Vision.Sound
def getSoundBytes(fileName):
	bytes = system.util.sendRequest('GatewayScripts', 'GetAlarmSound', {'fileName': fileName})
	return bytes
	
def getAvailableAlarmSounds():
	fileList = system.util.sendRequest('GatewayScripts', 'GetAlarmSoundList')
	fileDS = []
	for fileName in fileList:
		fileDS.append([fileName, fileName])
	
	return system.dataset.toDataSet(['Value', 'Label'], fileDS)
Then the binding on my Sound Player component's soundData property is:
runScript('Vision.Sound.getSoundBytes',0,{[client]AlarmSound})
For sound selection, I have a client settings popup that has a dropdown with the data property set to this binding:
runScript('Vision.Sound.getAvailableAlarmSounds', 0)
And the selectedStringValue property bound to my [client]AlarmSound tag.
I guess I maybe assumed that the Sound Player component essentially caches the sound bytes whenever the component is loaded or the sound file is changed. You could use a non-client tag also if you wanted it to change globally for everyone.