why do I get this error ??? : aud.error: AUD_FileFactory: File couldn't be read.

Hi again, this time I need to play a sound. Everything works well for the soundA but the soundB wich follows the same logic but replacing a with b will not work at all.

Everytime I press B while runing the script I get this error :

aud.error: AUD_FileFactory: File couldn’t be read.

import bge
from bge import logic
import aud 


#The actual scene in a word
scene = bge.logic.getCurrentScene()


#The controller holding this script
cont = logic.getCurrentController()
own = cont.owner


# my actuator is named SoundA and is used to play the corresponding sound
actA = cont.actuators["SoundA"]
actB = cont.actuators["SoundB"]


# pressA means when letter a is down
pressA = cont.sensors["KeyboardA"]
pressB = cont.sensors["KeyboardB"]


# get a list of the objects in the scene
objList = scene.objects


# get object named A
letterA = objList["Ak"]
letterB = objList["Bk"]


# get object named Score
score = objList["Score"]


# The old score of the player
oldScore = own.get("zScore")


# get the distance between them
distanceA = own.getDistanceTo(letterA)
distanceB = own.getDistanceTo(letterB)




# Create a variable and store the sound you want to reference once
if not 'init' in own: 


    own['init'] = 1


    own['soundA'] = aud.Factory(logic.expandPath('//1.wav'))
    own['soundB'] = aud.Factory(logic.expandPath('//2.wav')) # Create a factory (something that stores sounds) from a path.
    # The path is created by the bge.logic.expandPath() function. The string begins with "//", which signifies a path relative from the
    # blend file. So, "//ASound.wav" is referring to a wave file named "ASound.wav" that's in the same directory as the blend.






#If letter A is in the scene and the key A is pressed compare 
#the distance between The letter A and the Amarker
#Than add this value to the score
#Finaly destroy the letter A


if letterA:
    
    if pressA.positive:
        
        # The score given according to the distance
        scoreAdd = (int(100-(distanceA*2)))
        
        newScore = (oldScore+scoreAdd)
       
        score.text = str(newScore)
    
        aud.device().play(own['soundA']) # Use the sound device that the aud module retrieves to playback the sound factory; this process
        # returns a Handle. You can do a lot with Handle, like pitch individual playbacks of sounds and adjust volumes.
        letterA.endObject()
        
        own["zScore"] = newScore
        
if letterB:
    
    if pressB.positive:
        
        # The score given according to the distance
        scoreAdd = (int(100-(distanceB*2)))
        
        newScore = (oldScore+scoreAdd)
       
        score.text = str(newScore)
    
        aud.device().play(own['soundB'])# Use the sound device that the aud module retrieves to playback the sound factory; this process
        # returns a Handle. You can do a lot with Handle, like pitch individual playbacks of sounds and adjust volumes.
        letterB.endObject()
        
        own["zScore"] = newScore

I just dont get it everything seems to be exactly as for the A key but with B everywhere.

If anyone have an Idea Id be glad to ear it !

Why you write the code twice?

According to the mentioned error the sound file can’t be read. Either it is damaged or does not exist.

Like Monster mentioned, you should ensure the file exists (i.e. is named “2.wav” and is next to the blend file), and that it plays back fine. Also, you could clean up your script a bit to make it easier to read and deal with (i.e. you don’t need sound actuators since you’re doing everything with Audaspace). Also, you could print out the path to the file to ensure it’s correct (print out the logic.expandPath(’//2.wav’) part).

EDIT: If none of this helps, you could try packing your sounds and the blend file into a zip and uploading it to a file hosting service like Copy, Box, Dropbox, or Mediafire.

afaik the device should be created only once

i not know if this is the problem

in your case (with script mode) try to store the device in a property, or better in globalDict:


if not "init" in own:
  own["init"] = 1
  bge.logic.globalDict["device"] = aud.device() 

if pressA.positive:
  bge.logic.globalDict["device"].play(own['soundA'])

If any of the aforementioned solutions do not work, try playing an mp3 file. I was unable to play wav sounds in my builds recently, and I’m sure I didn’t disable any sound codecs

Sent from my Nexus 5 using Tapatalk

Hmm the code is all right I was wrong in the expandPath… basicly the sound is not with the blend as the soundA :S

Sorry for that waste of time :S

thx btw

Why you write the code twice?

I need to do so because every letters will have the same script with some variations like they spawn at a different location, they also all play a different sound.

For this reason I cant just use the same script over and over for each letters.

So I am creating in a single script (to make it eazy if I have some changes to do) with all the code for each letters.

Obviously I try to set everything as I want it to be for the final result before I create more letters as I dont want to have to rewhrite every lines for each letters if I need a change.

Finally now that I got those 2 letters working I figured a bug witch makes no sence to me yet but has to be fixed before I implement the other letters :S

When playing the game the letters A and B both get created 5 times .
The player will than hit A and B 5 times each. (everytime the player it A if A is in the scene it gets deleted and play
a sound , same for b)

The problem is that for some reason the last letter to stay in the scene doesnt want to get deleted anymore (or play its sound/add score).

*In other words deleting every instance of an object wont let the script run anymore

After reading the console I got that :
If the last letter to be in the screen is A - the console displays: ‘Bk’ not in list
If the last letter to be in the screen is B - the console displays: ‘Ak’ not in list

-this occurs as soon as all the object of an instance are deleted example:
I delete all 5 A’s , I cant delete anny B.
-Also if another A was to appear at that time, the script would work again
so I could delete all the B.

I dont get why the code looks for the letter B when we ask for A and vice versa.
If anyone as a logic explanation for this Id be glad to read about it.
Also if there is a way to solve this .

Thx again. (btw I love this forum)

This happens because your script searches the “objlist” list for “Ak” and “Bk” objects. If you delete them, then they’re no longer available to be found, so the script fails. You need to ensure they’re there before you continue.



letterA = objlist['Ak'] if 'Ak' in objlist else None

# And then later...

if letterA: # In Python a boolean check like this equates to "if letterA is not equal to None or 0, then it's true". So, if letterA is a reference to an existing object.


EDIT: A more efficient way to do this is to make a global dictionary (“logic.letters”, for example) with an empty list for each letter. You store letters as they are created (i.e. when they’re created, they run a simple script that adds their reference in their specific list for you to check). The reference is stored by letter (i.e. logic.letters[‘A’].append(obj) ). When you delete a letter, you remove its reference from the logic.letters dictionary.

EDIT 2: And yeah, the community’s pretty nice.

In addition, your code looks almost copied twice, meaning that you could simplify it into some reusable functions, e.g


import bge
from bge import logic
import aud 




#The actual scene in a word
scene = bge.logic.getCurrentScene()




#The controller holding this script
cont = logic.getCurrentController()
own = cont.owner




def setup_letter(cont, letter, sound):
	obj = cont.owner
	sound_path = logic.expandPath('//{}'.format(sound))


	try:
		letters = obj['letters']
	except KeyError:
		letters = obj['letters'] = {}
	
	letters[letter] = aud.Factory(sound_path)


def handle_letters(cont):
	obj = cont.owner
	scene = obj.scene


	for letter, sound in own['letters'].items():
		handle_letter(cont, letter, sound)


def handle_letter(cont, letter, sound):
	letter_name = '{}k'.format(letter)
	letter_objects = (o for o in scene.objects if o.name == letter_name)
	
	try:
		letter_obj = next(letter_objects)
	except StopIteration:
		return
	
	keyboard_sensor = cont.sensors['Keyboard{}'.format(letter)]
	
	if not keyboard_sensor.positive:
		return


	score = scene.objects['Score']
	old_score = own['zScore']
	
	distance = own.getDistanceTo(letter_obj)
	
	extra_score = round(100 - distance * 2)
	new_score = old_score + extra_score
	
	# Effect results
	score.text = str(new_score)
	letter_obj.endObject()
	own['zScore'] = new_score
	aud.device().play(sound)
	
	
if not "init" in own:
	setup_letter(cont, "A", "1.wav")
	setup_letter(cont, "B", "2.wav")


handle_letters(cont)

O.O omg…

I was actualy working on my script to make it look nicer and be clearer to the other python users but I think your script is better XD
Thancks guys this works perfectly and agoose77 you are awesome I just copy pasted the script and it works perfectly I just saved so much lines of coding by your help :stuck_out_tongue:
(I only changed one thing I was too lazy to convert the 2.mp3 to wav so i changed those 3 letters in your script)

Here look at what I had before you post this script!

import bge
from bge import logic
import aud

#The controller holding this script
cont = logic.getCurrentController()
own = cont.owner

#The actual scene in a word
scene = bge.logic.getCurrentScene()

get a list of the objects in the scene

objList = scene.objects

get the text object named Score

score = objList[“Score”]

The old score of the player (property variable)

oldScore = own.get(“zScore”)

#//--------------------------------------------------\#
# Here we store all the values for the letters

The object itselt: letter()

The keyboard Sensor for that letter: press()

The Distance from the letter to its marker: distance()

The Sound of this object: [‘sound()’]

#\--------------------------------------------------//#

get object named A

#letterA = objList[“Ak”]
#letterB = objList[“Bk”]
letterA = objlist[‘Ak’] if ‘Ak’ in objlist else None
letterB = objlist[‘Bk’] if ‘Bk’ in objlist else None

pressA means when letter a is down

pressA = cont.sensors[“KeyboardA”]
pressB = cont.sensors[“KeyboardB”]

get the distance between the letter and its marker

distanceA = own.getDistanceTo(letterA)
distanceB = own.getDistanceTo(letterB)

Create a variable and store the sound you want to reference once

if not ‘init’ in own:

own['init'] = 1

# The sound location (same as the blend file)
own['soundA'] = aud.Factory(logic.expandPath('//1.wav'))
own['soundB'] = aud.Factory(logic.expandPath('//2.mp3')) 

#//--------------------------------------------------\#
#If: letter A is in the scene
#and: the key A is pressed
#Than: compare the distance
#between: The letter A and the Amarker
#Than: add the distance to the score
#and: Play the sound A
#Finally: destroy the letter A
#\--------------------------------------------------//#

#Letter A script start---------------------------------#

if letterA:

if pressA.positive:
    
    
    scoreAdd = (int(100-(distanceA*2)))
    
    newScore = (oldScore+scoreAdd)
   
    score.text = str(newScore)

    aud.device().play(own['soundA']) 
    
    letterA.endObject()
    
    own["zScore"] = newScore

#Letter A script end---------------------------------#

#//--------------------------------------------------\#
#From here the script is the same for every letters.
#The only difference is that we replace the letter A
#in the variable letterA (x2), pressA, distanceA,
#and soundA for the letter used.
#\--------------------------------------------------//#

#Letter B script start---------------------------------#

if letterB:

if pressB.positive:
            
    scoreAdd = (int(100-(distanceB*2)))
    
    newScore = (oldScore+scoreAdd)
   
    score.text = str(newScore)

    aud.device().play(own['soundB'])
    
    letterB.endObject()
    
    own["zScore"] = newScore

#Letter B script end------------------------------------#

and to the garbage this script goes XD
(Now i need to understand how the new script works)

btw at this point Ill ask one more thing instead of opening a new thread.

basicly i want to print in the console the time that i press a key and wich key was pressed.

To do this I think i’ll use the timer property once more and add a if a key is pressed than print the key and timer

import bge
from bge import logic


ob = bge.logic.getCurrentController().owner


timer = ob.get('Timer')

if #now i dont know how to say on any keypressed
     print (the key pressed , (timer)

Thancks once again I really apreciate the help!

Potatobob, just a tip: you are using “quotes” for put the script, do not do that, use code tags.