]> git.basschouten.com Git - openhab-addons.git/blob
e4ac1604bb1859a2fb84ff851682cd83de98babf
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
7  * This program and the accompanying materials are made available under the
8  * terms of the Eclipse Public License 2.0 which is available at
9  * http://www.eclipse.org/legal/epl-2.0
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.doorbird.internal.audio;
14
15 import java.io.BufferedInputStream;
16 import java.io.IOException;
17 import java.io.InputStream;
18
19 import javax.sound.sampled.AudioFormat;
20 import javax.sound.sampled.AudioFormat.Encoding;
21 import javax.sound.sampled.AudioInputStream;
22 import javax.sound.sampled.AudioSystem;
23 import javax.sound.sampled.UnsupportedAudioFileException;
24
25 import org.eclipse.jdt.annotation.NonNullByDefault;
26 import org.eclipse.jdt.annotation.Nullable;
27
28 /**
29  * This class convert a stream to the normalized ulaw
30  * format wanted by doorbird api
31  *
32  * @author Gwendal Roulleau - Initial contribution
33  */
34 @NonNullByDefault
35 public class ConvertedInputStream extends InputStream {
36
37     private static final javax.sound.sampled.AudioFormat INTERMEDIARY_PCM_FORMAT = new javax.sound.sampled.AudioFormat(
38             javax.sound.sampled.AudioFormat.Encoding.PCM_SIGNED, 8000, 16, 1, 2, 8000, false);
39     private static final javax.sound.sampled.AudioFormat TARGET_ULAW_FORMAT = new javax.sound.sampled.AudioFormat(
40             javax.sound.sampled.AudioFormat.Encoding.ULAW, 8000, 8, 1, 1, 8000, false);
41
42     private AudioInputStream pcmUlawInputStream;
43
44     public ConvertedInputStream(InputStream innerInputStream) throws UnsupportedAudioFileException, IOException {
45
46         pcmUlawInputStream = getULAWStream(new BufferedInputStream(innerInputStream));
47     }
48
49     public AudioInputStream getAudioInputStream() {
50         return pcmUlawInputStream;
51     }
52
53     @Override
54     public int read(byte @Nullable [] b) throws IOException {
55         return pcmUlawInputStream.read(b);
56     }
57
58     @Override
59     public int read(byte @Nullable [] b, int off, int len) throws IOException {
60         return pcmUlawInputStream.read(b, off, len);
61     }
62
63     @Override
64     public byte[] readAllBytes() throws IOException {
65         return pcmUlawInputStream.readAllBytes();
66     }
67
68     @Override
69     public byte[] readNBytes(int len) throws IOException {
70         return pcmUlawInputStream.readNBytes(len);
71     }
72
73     @Override
74     public int readNBytes(byte @Nullable [] b, int off, int len) throws IOException {
75         return pcmUlawInputStream.readNBytes(b, off, len);
76     }
77
78     @Override
79     public int read() throws IOException {
80         return pcmUlawInputStream.read();
81     }
82
83     @Override
84     public void close() throws IOException {
85         pcmUlawInputStream.close();
86     }
87
88     /**
89      * Ensure the right ULAW format by converting if necessary (two pass)
90      *
91      * @param originalInputStream a mark/reset compatible stream
92      *
93      * @return A ULAW stream (1 channel, 8000hz, 16 bit signed)
94      * @throws IOException
95      * @throws UnsupportedAudioFileException
96      */
97     private AudioInputStream getULAWStream(InputStream originalInputStream)
98             throws UnsupportedAudioFileException, IOException {
99
100         try {
101             AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(originalInputStream);
102             AudioFormat format = audioInputStream.getFormat();
103
104             boolean frameRateOk = Math.abs(format.getFrameRate() - 8000) < 1;
105             boolean sampleRateOk = Math.abs(format.getSampleRate() - 8000) < 1;
106
107             if (format.getEncoding().equals(Encoding.ULAW) && format.getChannels() == 1 && frameRateOk && sampleRateOk
108                     && format.getFrameSize() == 1 && format.getSampleSizeInBits() == 8) {
109                 return audioInputStream;
110             }
111
112             // we have to use an intermediary format with 16 bits, even if the final target format is 8 bits
113             // this is a limitation of the conversion library, which only accept 16 bits input to convert to ULAW.
114             AudioInputStream targetPCMFormat = audioInputStream;
115             if (format.getChannels() != 1 || !frameRateOk || !sampleRateOk || format.getFrameSize() != 2
116                     || format.getSampleSizeInBits() != 16) {
117                 targetPCMFormat = AudioSystem.getAudioInputStream(INTERMEDIARY_PCM_FORMAT, audioInputStream);
118             }
119
120             return AudioSystem.getAudioInputStream(TARGET_ULAW_FORMAT, targetPCMFormat);
121         } catch (IllegalArgumentException iarg) {
122             throw new UnsupportedAudioFileException(
123                     "Cannot convert audio input to ULAW target format. Cause: " + iarg.getMessage());
124         }
125     }
126 }