旁白
这周老大安排了一个活儿,前端传一组摩尔斯电码过来,将其装成音频流通过WebSocket推给前端进行播放,由于场景的特殊还需要控制"点" "划"播报的时间长短。当时心想Java还能生成这个玩意儿?通过查阅了大量的资料后,确定了Java的确可以实现,不得不感叹这Java是真滴厉害。相关资料已放到下方链接。 音频基础知识 摩尔斯电码表 Java 生成摩尔斯电码音频流代码
转音频代码
初始化摩尔斯电码映射
public class MorseEncoder {
private final Map<String,String> codeMap = new HashMap<>();
private Integer dotRatio = 1;
private Integer rowRatio = 3;
private Integer blankRatio = 5;
private final String dotString = ".";
private final String rowString = "-";
private final String minInterval = "@";
private final String maxInterval = "/";
private final String blank = " ";
@PostConstruct
public void initMap(){
codeMap.put("A",". -");
codeMap.put("B","- . . .");
codeMap.put("C","- . - .");
codeMap.put("D","- . .");
codeMap.put("E",".");
codeMap.put("F",". . - .");
codeMap.put("G","- - .");
codeMap.put("H",". . . .");
codeMap.put("I",". .");
codeMap.put("J",". - - -");
codeMap.put("K","- . -");
codeMap.put("L",". - . .");
codeMap.put("M","- -");
codeMap.put("N","- .");
codeMap.put("O","- - -");
codeMap.put("P",". - - .");
codeMap.put("Q","- - . -");
codeMap.put("R",". - .");
codeMap.put("S",". . .");
codeMap.put("T","-");
codeMap.put("U",". . -");
codeMap.put("V",". . . -");
codeMap.put("W",". - -");
codeMap.put("X","- . . -");
codeMap.put("Y","- . - -");
codeMap.put("Z","- - . .");
codeMap.put("1",". - - - -");
codeMap.put("2",". . - - -");
codeMap.put("3",". . . - -");
codeMap.put("4",". . . . -");
codeMap.put("5",". . . . .");
codeMap.put("6","- . . . .");
codeMap.put("7","- - . . .");
codeMap.put("8","- - - . .");
codeMap.put("9","- - - - .");
codeMap.put("0","- - - - -");
}
}
字符串转电码
public String string2MorseCode(List<String> args,Integer type){
StringBuilder result = new StringBuilder();
if(type.compareTo(1) == 0 ){
for (String arg : args) {
String morse = codeMap.get(arg.toUpperCase());
if(morse == null){
throw new RuntimeException(arg+"不是摩尔斯电码");
}
result.append(morse)
.append(minInterval);
}
}else {
for (String arg : args) {
for (int i = 0; i < arg.length(); i++) {
String code = String.valueOf(arg.charAt(i));
String morse = codeMap.get(code.toUpperCase());
if(morse == null){
throw new RuntimeException(arg+"不是摩尔斯电码");
}
result.append(morse)
.append(minInterval);
}
result.append(maxInterval);
}
}
return result.toString();
}
电码转音频
public byte[] codeConvert2Sound(String codeString,int reta){
int dot = reta * dotRatio;
int row = reta * rowRatio;
int blank = reta * blankRatio;
ArrayList<Byte> rawData = new ArrayList<Byte>();
for(int i=0; i<codeString.length(); i++){
int soundLength = 0;
int frequency = 1450;
String code = Character.toString(codeString.charAt(i));
if (code.equals(rowString)) {
soundLength = row;
} else if (code.equals(dotString)) {
soundLength = dot;
} else if (code.equals(minInterval)) {
soundLength = row;
frequency = 0;
} else if (code.equals(maxInterval)) {
soundLength = blank;
frequency = 0;
}else if(code.equals(this.blank)){
soundLength = dot;
frequency = 0;
}
for ( int k = 0; k < soundLength * (float)44100 / 1000; k++ ) {
double angle = k / ( (float)44100 / frequency ) * 2.0 * Math.PI;
rawData.add( (byte)( Math.sin( angle ) * 100 ) );
}
}
byte[] audio = new byte[rawData.size()];
for (int i=0; i<rawData.size(); i++){
audio[i] = rawData.get(i);
}
return audio;
}
存入到文件中 wav格式
private void save2File(byte[] audio) {
InputStream byteArrayInputStream = new ByteArrayInputStream(audio);
AudioFormat audioFormat = new AudioFormat( (float)44100, 8, 1, true, false );
AudioInputStream audioInputStream = new AudioInputStream( byteArrayInputStream, audioFormat, audio.length / audioFormat.getFrameSize() );
try {
String format = LocalDateTime.now().format(DateTimeFormatter.ofPattern("HH-mm-ss"));
AudioSystem.write( audioInputStream, AudioFileFormat.Type.WAVE, new File( "D:\\morse-code-"+format +".wav" ));
}
catch ( Exception e ) {
e.printStackTrace();
}
}
生成WAV头文件
public static byte[] writeWavFileHeader(long totalAudioLen, long longSampleRate,
int channels, int audioFormat) throws IOException {
byte[] header = generateWavFileHeader(totalAudioLen, longSampleRate, channels, audioFormat);
return header;
}
private static byte[] generateWavFileHeader(long totalAudioLen, long longSampleRate, int channels,int audioFormat) {
long totalDataLen = totalAudioLen + 36;
long byteRate = longSampleRate * 2 * channels;
byte[] header = new byte[44];
header[0] = 'R';
header[1] = 'I';
header[2] = 'F';
header[3] = 'F';
header[4] = (byte) (totalDataLen & 0xff);
header[5] = (byte) ((totalDataLen >> 8) & 0xff);
header[6] = (byte) ((totalDataLen >> 16) & 0xff);
header[7] = (byte) ((totalDataLen >> 24) & 0xff);
header[8] = 'W';
header[9] = 'A';
header[10] = 'V';
header[11] = 'E';
header[12] = 'f';
header[13] = 'm';
header[14] = 't';
header[15] = ' ';
header[16] = 16;
header[17] = 0;
header[18] = 0;
header[19] = 0;
header[20] = 1;
header[21] = 0;
header[22] = (byte) channels;
header[23] = 0;
header[24] = (byte) (longSampleRate & 0xff);
header[25] = (byte) ((longSampleRate >> 8) & 0xff);
header[26] = (byte) ((longSampleRate >> 16) & 0xff);
header[27] = (byte) ((longSampleRate >> 24) & 0xff);
header[28] = (byte) (byteRate & 0xff);
header[29] = (byte) ((byteRate >> 8) & 0xff);
header[30] = (byte) ((byteRate >> 16) & 0xff);
header[31] = (byte) ((byteRate >> 24) & 0xff);
header[32] = (byte) (2 * channels);
header[33] = 0;
header[34] = (byte) audioFormat;
header[35] = 0;
header[36] = 'd';
header[37] = 'a';
header[38] = 't';
header[39] = 'a';
header[40] = (byte) (totalAudioLen & 0xff);
header[41] = (byte) ((totalAudioLen >> 8) & 0xff);
header[42] = (byte) ((totalAudioLen >> 16) & 0xff);
header[43] = (byte) ((totalAudioLen >> 24) & 0xff);
return header;
}
测试
@Test
public void morseCodeTest() throws IOException {
MorseEncoder encoder = new MorseEncoder();
List<String> args = new ArrayList<>();
args.add("ttt");
args.add("000");
String code = encoder.string2MorseCode(args, 2);
byte[] bytes = encoder.codeConvert2Sound(code, 100);
byte[] header = encoder.writeWavFileHeader(bytes.length, 44100, 1, 8);
ByteArrayBuilder builder = new ByteArrayBuilder();
builder.write(header);
builder.write(bytes);
byte[] data = builder.toByteArray();
File file = new File("D:\\test.wav");
OutputStream os = new FileOutputStream(file);
os.write(data);
}
效果 播放出来的效果也是跟预期的一样 代码地址 https://gitee.com/wsl__cn/morse-code-convert-audio.git
|