aboutsummaryrefslogtreecommitdiffstats
path: root/src/com/jsyn/util/soundfile/AudioFileParser.java
blob: e7bb0662afd056d2334af85a3accda0431c33469 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/*
 * Copyright 2001 Phil Burk, Mobileer Inc
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.jsyn.util.soundfile;

import java.io.IOException;
import java.util.HashMap;

import com.jsyn.data.FloatSample;
import com.jsyn.data.SampleMarker;

/**
 * Base class for various types of audio specific file parsers.
 * 
 * @author (C) 2001 Phil Burk, SoftSynth.com
 */

abstract class AudioFileParser implements ChunkHandler {
    IFFParser parser;
    protected byte[] byteData;
    boolean ifLoadData = true; /* If true, load sound data into memory. */
    long dataPosition; /*
                        * Number of bytes from beginning of file where sound data resides.
                        */
    protected int bitsPerSample;
    protected int bytesPerFrame; // in the file
    protected int bytesPerSample; // in the file
    protected HashMap<Integer, SampleMarker> cueMap = new HashMap<Integer, SampleMarker>();
    protected short samplesPerFrame;
    protected double frameRate;
    protected int numFrames;
    protected double originalPitch = 60.0;
    protected int sustainBegin = -1;
    protected int sustainEnd = -1;

    public AudioFileParser() {
    }

    /**
     * @return Number of bytes from beginning of stream where sound data resides.
     */
    public long getDataPosition() {
        return dataPosition;
    }

    /**
     * This can be read by another thread when load()ing a sample to determine how many bytes have
     * been read so far.
     */
    public synchronized long getNumBytesRead() {
        IFFParser p = parser; // prevent race
        if (p != null)
            return p.getOffset();
        else
            return 0;
    }

    /**
     * This can be read by another thread when load()ing a sample to determine how many bytes need
     * to be read.
     */
    public synchronized long getFileSize() {
        IFFParser p = parser; // prevent race
        if (p != null)
            return p.getFileSize();
        else
            return 0;
    }

    protected SampleMarker findOrCreateCuePoint(int uniqueID) {
        SampleMarker cuePoint = cueMap.get(uniqueID);
        if (cuePoint == null) {
            cuePoint = new SampleMarker();
            cueMap.put(uniqueID, cuePoint);
        }
        return cuePoint;
    }

    public FloatSample load(IFFParser parser) throws IOException {
        this.parser = parser;
        parser.parseAfterHead(this);
        return finish();
    }

    abstract FloatSample finish() throws IOException;

    FloatSample makeSample(float[] floatData) throws IOException {
        FloatSample floatSample = new FloatSample(floatData, samplesPerFrame);

        floatSample.setChannelsPerFrame(samplesPerFrame);
        floatSample.setFrameRate(frameRate);
        floatSample.setPitch(originalPitch);

        if (sustainBegin >= 0) {
            floatSample.setSustainBegin(sustainBegin);
            floatSample.setSustainEnd(sustainEnd);
        }

        for (SampleMarker marker : cueMap.values()) {
            floatSample.addMarker(marker);
        }

        /* Set Sustain Loop by assuming first two markers are loop points. */
        if (floatSample.getMarkerCount() >= 2) {
            floatSample.setSustainBegin(floatSample.getMarker(0).position);
            floatSample.setSustainEnd(floatSample.getMarker(1).position);
        }
        return floatSample;
    }

    protected String parseString(IFFParser parser, int textLength) throws IOException {
        byte[] bar = new byte[textLength];
        parser.read(bar);
        return new String(bar);
    }
}