~brzeti/patat/dev

« back to all changes in this revision

Viewing changes to src/com/brackeen/javagamebook/sound/Filter3d.java

  • Committer: Arthur Skonecki
  • Date: 2008-12-02 12:59:20 UTC
  • Revision ID: admin@adb.cba.pl-20081202125920-hmvdzcrxgq1tl514
initial project's files submission

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
package com.brackeen.javagamebook.sound;
 
2
 
 
3
import com.brackeen.javagamebook.graphics.Sprite;
 
4
 
 
5
/**
 
6
    The Filter3d class is a SoundFilter that creates a 3d sound
 
7
    effect. The sound is filtered so that it is quiter the farther
 
8
    away the sound source is from the listener.
 
9
    <p>Possible ideas to extend this class:
 
10
    <ul><li>pan the sound to the left and right speakers
 
11
    </ul>
 
12
    @see FilteredSoundStream
 
13
*/
 
14
public class Filter3d extends SoundFilter {
 
15
 
 
16
    // number of samples to shift when changing the volume.
 
17
    private static final int NUM_SHIFTING_SAMPLES = 500;
 
18
 
 
19
    private Sprite source;
 
20
    private Sprite listener;
 
21
    private int maxDistance;
 
22
    private float lastVolume;
 
23
 
 
24
    /**
 
25
        Creates a new Filter3d object with the specified source
 
26
        and listener Sprites. The Sprite's position can be
 
27
        changed while this filter is running.
 
28
        <p> The maxDistance parameter is the maximum distance
 
29
        that the sound can be heard.
 
30
    */
 
31
    public Filter3d(Sprite source, Sprite listener,
 
32
        int maxDistance)
 
33
    {
 
34
        this.source = source;
 
35
        this.listener = listener;
 
36
        this.maxDistance = maxDistance;
 
37
        this.lastVolume = 0.0f;
 
38
    }
 
39
 
 
40
 
 
41
    /**
 
42
        Filters the sound so that it gets more quiet with
 
43
        distance.
 
44
    */
 
45
    public void filter(byte[] samples, int offset, int length) {
 
46
 
 
47
        if (source == null || listener == null) {
 
48
            // nothing to filter - return
 
49
            return;
 
50
        }
 
51
 
 
52
        // calculate the listener's distance from the sound source
 
53
        float dx = (source.getX() - listener.getX());
 
54
        float dy = (source.getY() - listener.getY());
 
55
        float distance = (float)Math.sqrt(dx * dx + dy * dy);
 
56
 
 
57
        // set volume from 0 (no sound) to 1
 
58
        float newVolume = (maxDistance - distance) / maxDistance;
 
59
        if (newVolume <= 0) {
 
60
            newVolume = 0;
 
61
        }
 
62
 
 
63
        // set the volume of the sample
 
64
        int shift = 0;
 
65
        for (int i=offset; i<offset+length; i+=2) {
 
66
 
 
67
            float volume = newVolume;
 
68
 
 
69
            // shift from the last volume to the new volume
 
70
            if (shift < NUM_SHIFTING_SAMPLES) {
 
71
                volume = lastVolume + (newVolume - lastVolume) *
 
72
                    shift / NUM_SHIFTING_SAMPLES;
 
73
                shift++;
 
74
            }
 
75
 
 
76
            // change the volume of the sample
 
77
            short oldSample = getSample(samples, i);
 
78
            short newSample = (short)(oldSample * volume);
 
79
            setSample(samples, i, newSample);
 
80
        }
 
81
 
 
82
        lastVolume = newVolume;
 
83
    }
 
84
 
 
85
}