1 package org.daisy.pipeline.audio.impl;
2
3 import java.io.File;
4 import java.io.FileInputStream;
5 import java.io.FileOutputStream;
6 import java.time.Duration;
7 import java.util.Map;
8 import java.util.Optional;
9
10 import javax.sound.sampled.AudioFileFormat;
11 import javax.sound.sampled.AudioFormat;
12 import javax.sound.sampled.AudioFormat.Encoding;
13 import javax.sound.sampled.AudioInputStream;
14 import javax.sound.sampled.AudioSystem;
15
16 import org.daisy.pipeline.audio.AudioClip;
17 import org.daisy.pipeline.audio.AudioEncoder;
18 import org.daisy.pipeline.audio.AudioEncoderService;
19 import org.daisy.pipeline.audio.AudioUtils;
20
21 import org.osgi.service.component.annotations.Component;
22
23 @Component(
24 name = "system-audio-encoder",
25 immediate = true,
26 service = { AudioEncoderService.class }
27 )
28 public class SystemAudioEncoder implements AudioEncoderService {
29
30 @Override
31 public boolean supportsFileType(AudioFileFormat.Type fileType) {
32 return AudioSystem.isFileTypeSupported(fileType);
33 }
34
35 @Override
36 public Optional<AudioEncoder> newEncoder(Map<String,String> params) {
37 if (instance == null)
38 instance = new AudioEncoder() {
39 @Override
40 public AudioClip encode(AudioInputStream pcm, AudioFileFormat.Type outputFileType, File outputFile) throws Throwable {
41 AudioFormat format = pcm.getFormat();
42 if (outputFileType == AudioFileFormat.Type.WAVE) {
43 if (format.getEncoding() == Encoding.PCM_FLOAT) {
44 if (format.isBigEndian()) {
45
46
47
48
49 return encode(
50 AudioUtils.convertAudioStream(
51 new AudioFormat(format.getEncoding(),
52 format.getSampleRate(),
53 format.getSampleSizeInBits(),
54 format.getChannels(),
55 format.getFrameSize(),
56 format.getFrameRate(),
57 false),
58 pcm),
59 outputFileType,
60 outputFile);
61 } else {
62
63
64
65 File tmpFile = File.createTempFile("wrong-header-", ".wav.tmp");
66 tmpFile.deleteOnExit();
67 AudioSystem.write(pcm, outputFileType, tmpFile);
68 try (FileInputStream wrongFile = new FileInputStream(tmpFile);
69 FileOutputStream correctedFile = new FileOutputStream(outputFile)) {
70 byte[] header = new byte[44];
71 wrongFile.read(header);
72
73 header[20] = (byte)3;
74 correctedFile.write(header);
75 byte[] buf = new byte[1024];
76 while (true) {
77 int bytesRead = wrongFile.read(buf);
78 if (bytesRead == -1)
79 break;
80 correctedFile.write(buf, 0, bytesRead);
81 }
82 }
83 tmpFile.delete();
84 }
85 } else if (format.getEncoding() == Encoding.PCM_UNSIGNED
86 && format.getSampleSizeInBits() > 8
87 && !format.isBigEndian()) {
88
89
90
91
92
93 return encode(
94 AudioUtils.convertAudioStream(
95 new AudioFormat(format.getSampleRate(),
96 format.getSampleSizeInBits(),
97 format.getChannels(),
98 false,
99 true),
100 pcm),
101 outputFileType,
102 outputFile);
103 } else
104 AudioSystem.write(pcm, outputFileType, outputFile);
105 } else
106 AudioSystem.write(pcm, outputFileType, outputFile);
107 return new AudioClip(outputFile, Duration.ZERO, AudioUtils.getDuration(pcm));
108 }
109 };
110 return Optional.of(instance);
111 }
112
113 private static AudioEncoder instance = null;
114
115 }