-
-
Notifications
You must be signed in to change notification settings - Fork 3
/
DividedSmafWithVoiceMaker.java
163 lines (143 loc) · 6.25 KB
/
DividedSmafWithVoiceMaker.java
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
/*
* Copyright (c) 2008 by Naohide Sano, All rights reserved.
*
* Programmed by Naohide Sano
*/
package vavi.sound.sampled.smaf;
import java.io.File;
import java.io.IOException;
import java.lang.System.Logger;
import java.lang.System.Logger.Level;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.UnsupportedAudioFileException;
import org.klab.commons.cli.Argument;
import org.klab.commons.cli.HelpOption;
import org.klab.commons.cli.Option;
import org.klab.commons.cli.Options;
import vavi.sound.sampled.FilterChain;
import vavi.sound.sampled.WaveDivider;
import vavi.sound.smaf.InvalidSmafDataException;
import static java.lang.System.getLogger;
/**
* DividedSmafWithVoiceMaker.
*
* @author <a href="mailto:[email protected]">Naohide Sano</a> (nsano)
* @version 0.00 080415 nsano initial version <br>
*/
class DividedSmafWithVoiceMaker extends SmafWithVoiceMaker {
private static final Logger logger = getLogger(DividedSmafWithVoiceMaker.class.getName());
/** source PCM */
private final AudioInputStream sourceAis;
/** output base directory */
private final String directory;
/** output file template (use {@link String#format(String, Object...)}) */
private final String base;
/**
*
* @param sourceAis source PCM
* @param directory output base directory, directory "mmf" will be added
* @param base output file template
* @param time dividing time in second
* @param samplingRate ADPCM sampling rate [Hz]
* @param bits ADPCM sampling bits
* @param channels
* @param masterVolume [%]
* @param adpcmVolume [%]
*/
public DividedSmafWithVoiceMaker(AudioInputStream sourceAis, String directory, String base, float time, int samplingRate, int bits, int channels, int masterVolume, int adpcmVolume) {
super(time, samplingRate, bits, channels, masterVolume, adpcmVolume);
this.sourceAis = sourceAis;
this.directory = directory + File.separator + "mmf"; // TODO dependence on mmf is not good
this.base = base;
}
/** */
private class Event implements WaveDivider.Event {
/** total size written */
int r = 0;
@Override
public void exec(WaveDivider.Chunk chunk) throws IOException {
try {
File file = new File(directory, String.format(base, chunk.sequence + 1));
logger.log(Level.DEBUG, "file: " + file + ", " + directory + ", " + base + ", " + (chunk.sequence + 1));
r += createSMAF(chunk.buffer, file);
} catch (InvalidSmafDataException e) {
throw new IOException(e);
}
}
}
/**
*
* @throws IOException
* @throws UnsupportedAudioFileException
* @throws InvalidSmafDataException
* @return total size written
*/
@Override
public int create() throws IOException, UnsupportedAudioFileException, InvalidSmafDataException {
long t = System.currentTimeMillis();
// divide
Event event = new Event();
WaveDivider waveDivider = WaveDivider.Factory.getWaveDivider(sourceAis);
logger.log(Level.DEBUG, "1: " + (System.currentTimeMillis() - t));
t = System.currentTimeMillis();
waveDivider.divide(time, event);
logger.log(Level.DEBUG, "2: " + (System.currentTimeMillis() - t));
t = System.currentTimeMillis();
return event.r;
}
//----
@Options
@HelpOption(argName = "help", option = "?", description = "print this help")
public static class Arguments {
@Argument(index = 0)
File file;
@Option(argName = "output", option = "o", args = 1, required = false, description = "output mmf filename base (use java.lang.String#format)")
String directory = ".";
@Option(argName = "template", option = "t", required = false, args = 1, description = "output base directory")
String base = "%s/out_%d.mmf";
@Option(argName = "model", option = "m", required = false, args = 1, description = "terminal model")
String model = defaultModel;
@Option(argName = "size", option = "s", required = false, args = 1, description = "chunk time in [sec]")
float time = 10;
@Option(argName = "rate", option = "r", required = false, args = 1, description = "adpcm sampling rate [Hz]")
int samplingRate = 16000;
@Option(argName = "bits", option = "b", required = false, args = 1, description = "adpcm sampling bits")
int bits = 4;
@Option(argName = "channels", option = "c", required = false, args = 1, description = "adpcm channels")
int channels = 1;
@Option(argName = "masterVolume", option = "v", required = false, args = 1, description = "master volume in [%]")
int masterVolume = 100;
@Option(argName = "adpcmVolume", option = "a", required = false, args = 1, description = "adpcm volume in [%]")
int adpcmVolume = 100;
}
/**
* Creates .mmf w/ voice file.
*
* @param args input wave file
* -o output base directory
* -t output mmf filename base (use java.lang.String#format)
* -s chunk time [second]
* -r adpcm sampling rate [Hz]
* -b adpcm sampling bits
* -c adpcm channels
* -v master volume [%]
* -a adpcm volume [%]
*/
public static void main(String[] args) {
try {
Arguments arguments = new Arguments();
Options.Util.bind(args, arguments);
// create
AudioInputStream ais = AudioSystem.getAudioInputStream(arguments.file);
FilterChain filterChain = new FilterChain();
DividedSmafWithVoiceMaker swvm = new DividedSmafWithVoiceMaker(filterChain.doFilter(ais), arguments.directory, arguments.base, arguments.time, arguments.samplingRate, arguments.bits, arguments.channels, arguments.masterVolume, arguments.adpcmVolume);
swvm.create();
// done
System.exit(0);
} catch (Exception e) {
e.printStackTrace(System.err);
System.exit(1);
}
}
}