I think your implementation assumes that the sound level in a cell is cumulative, and that the amplitude simply moves outwards evenly in all directions. Sound doesn't spread out, frame by frame, it's either playing or it isn't, and you want to find out the amplitude to play it at for any given point.
Raycasting through the tiles is one way (and probably the most effective way) of doing it. Just draw a line between emitter and receiver, and subtract the dampening value of each cell along the way. If the number is positive, you play the sound.
If you want to model indirect sound, then you'll have to path-find. Treat the emitter as the root of your tree, and model each adjacent cell as a linked node. Each link has a cost, subtracted from the current volume. Keep traversing through the graph until either you find the receiver or your volume drops below zero (if it does, backtrack and try another path). If there are no paths to the receiver with a positive volume, your emitter can't be heard. NB: you can't just give up traversing when you find the receiver, because there may be multiple paths from emitter to receiver, and you need the one with the highest volume.
If you're modelling AI that care about where the sound came from, the latter approach will help - an AI would be 'hearing' the sound come from direction of the last segment on the path. Nicely, if there are two audible paths to the receiver, they AI could be confused about the multiple sounds and which direction to take.