]> git.basschouten.com Git - openhab-addons.git/blob
8c8a09db44564f907a7029ae493e750ce9ce3ebb
[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         pcmUlawInputStream = getULAWStream(new BufferedInputStream(innerInputStream));
46     }
47
48     public AudioInputStream getAudioInputStream() {
49         return pcmUlawInputStream;
50     }
51
52     @Override
53     public int read(byte @Nullable [] b) throws IOException {
54         return pcmUlawInputStream.read(b);
55     }
56
57     @Override
58     public int read(byte @Nullable [] b, int off, int len) throws IOException {
59         return pcmUlawInputStream.read(b, off, len);
60     }
61
62     @Override
63     public byte[] readAllBytes() throws IOException {
64         return pcmUlawInputStream.readAllBytes();
65     }
66
67     @Override
68     public byte[] readNBytes(int len) throws IOException {
69         return pcmUlawInputStream.readNBytes(len);
70     }
71
72     @Override
73     public int readNBytes(byte @Nullable [] b, int off, int len) throws IOException {
74         return pcmUlawInputStream.readNBytes(b, off, len);
75     }
76
77     @Override
78     public int read() throws IOException {
79         return pcmUlawInputStream.read();
80     }
81
82     @Override
83     public void close() throws IOException {
84         pcmUlawInputStream.close();
85     }
86
87     /**
88      * Ensure the right ULAW format by converting if necessary (two pass)
89      *
90      * @param originalInputStream a mark/reset compatible stream
91      *
92      * @return A ULAW stream (1 channel, 8000hz, 16 bit signed)
93      * @throws IOException
94      * @throws UnsupportedAudioFileException
95      */
96     private AudioInputStream getULAWStream(InputStream originalInputStream)
97             throws UnsupportedAudioFileException, IOException {
98         try {
99             AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(originalInputStream);
100             AudioFormat format = audioInputStream.getFormat();
101
102             boolean frameRateOk = Math.abs(format.getFrameRate() - 8000) < 1;
103             boolean sampleRateOk = Math.abs(format.getSampleRate() - 8000) < 1;
104
105             if (format.getEncoding().equals(Encoding.ULAW) && format.getChannels() == 1 && frameRateOk && sampleRateOk
106                     && format.getFrameSize() == 1 && format.getSampleSizeInBits() == 8) {
107                 return audioInputStream;
108             }
109
110             // we have to use an intermediary format with 16 bits, even if the final target format is 8 bits
111             // this is a limitation of the conversion library, which only accept 16 bits input to convert to ULAW.
112             AudioInputStream targetPCMFormat = audioInputStream;
113             if (format.getChannels() != 1 || !frameRateOk || !sampleRateOk || format.getFrameSize() != 2
114                     || format.getSampleSizeInBits() != 16) {
115                 targetPCMFormat = AudioSystem.getAudioInputStream(INTERMEDIARY_PCM_FORMAT, audioInputStream);
116             }
117
118             return AudioSystem.getAudioInputStream(TARGET_ULAW_FORMAT, targetPCMFormat);
119         } catch (IllegalArgumentException iarg) {
120             throw new UnsupportedAudioFileException(
121                     "Cannot convert audio input to ULAW target format. Cause: " + iarg.getMessage());
122         }
123     }
124 }