├── .gitignore ├── atlassian-ide-plugin.xml ├── custom_doc.txt ├── gpl-3.0.txt ├── pom.xml ├── readme.txt └── src ├── main └── java │ └── org │ └── asteriskjava │ └── iax │ ├── audio │ ├── encodings │ │ └── gsm │ │ │ ├── Add.java │ │ │ ├── Encoder.java │ │ │ ├── GSMDecoder.java │ │ │ ├── Gsm_Def.java │ │ │ ├── Gsm_State.java │ │ │ ├── InvalidGSMFrameException.java │ │ │ ├── Long_term.java │ │ │ ├── Lpc.java │ │ │ ├── Rpe.java │ │ │ └── Short_term.java │ └── javasound │ │ ├── ABuffer.java │ │ ├── AEC.java │ │ ├── AbstractAudio.java │ │ ├── Audio8k.java │ │ ├── AudioAlaw.java │ │ ├── AudioGSM.java │ │ ├── AudioInterface.java │ │ ├── AudioProperties.java │ │ └── AudioUlaw.java │ ├── protocol │ ├── AudioSender.java │ ├── Binder.java │ ├── BinderSE.java │ ├── Call.java │ ├── CallManager.java │ ├── ControlFrame.java │ ├── DtmfFrame.java │ ├── Frame.java │ ├── Friend.java │ ├── FullFrame.java │ ├── IAX2ProtocolException.java │ ├── InfoElement.java │ ├── Log.java │ ├── MiniFrame.java │ ├── ProtocolControlFrame.java │ ├── ProtocolControlFrameNew.java │ ├── ProtocolEventListener.java │ ├── Ringer.java │ ├── VoiceFrame.java │ └── ring.wav │ ├── ui │ ├── BeanCanApplet.java │ ├── BeanCanFrame.java │ ├── BeanCanFrameManager.java │ └── GuiEventSender.java │ └── util │ ├── ByteBuffer.java │ ├── DTMFGenerator.java │ ├── GeneralDigest.java │ └── MD5Digest.java ├── site ├── apt │ ├── building.apt │ ├── faq.apt │ ├── index.apt │ ├── patch.apt │ └── tutorial.apt ├── resources │ ├── demo.html │ └── images │ │ └── asterisk-java.png └── site.xml └── test └── java └── org └── asteriskjava └── iax └── util └── MD5DigestTest.java /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | -------------------------------------------------------------------------------- /atlassian-ide-plugin.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10d510c7-303b-4eb7-8c6f-bfe79b882f16 6 | reucon 7 | https://build.reucon.com 8 | false 9 | true 10 | 11 | 12 | 13 | 14 | 15 | 16 | af4ea5dd-39e6-4a0a-99ac-d18be6530ab4 17 | reucon 18 | https://fisheye.reucon.com 19 | true 20 | 21 | 22 | e691789c-0e64-480d-9199-02447fe7e925 23 | reucon 24 | https://issues.reucon.com 25 | 26 | 27 | af4ea5dd-39e6-4a0a-99ac-d18be6530ab4 28 | af4ea5dd-39e6-4a0a-99ac-d18be6530ab4 29 | repos 30 | asterisk-java-iax/trunk 31 | e691789c-0e64-480d-9199-02447fe7e925 32 | 33 | 34 | -------------------------------------------------------------------------------- /custom_doc.txt: -------------------------------------------------------------------------------- 1 | how to compile: 2 | mvn clean install 3 | 4 | how to self-sign the jar: 5 | 6 | keytool -genkey -keystore keystore_file -alias jdc 7 | 8 | jarsigner -keystore keystore_file file_to_sign.jar jdc 9 | 10 | (or maybe use some maven magic) 11 | 12 | note to self: 13 | 14 | this applet will be able to share 15 | device audio with other application 16 | on a linux machine only if you use 17 | java 1.7 plugin. prev version don't 18 | work with pulseaudio and want to access 19 | the device audio in exclusive mode. 20 | 21 | openjdk don't work well, choppy audio, 22 | missing frame, mr roboto... 23 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | org.asteriskjava 5 | asterisk-java-iax 6 | Asterisk-Java IAX 7 | 1.0.0-SNAPSHOT 8 | Java library for the IAX protocol. 9 | http://asterisk-java.org/ 10 | 11 | 12 | GNU General Public License, Version 3 13 | http://www.gnu.org/licenses/gpl.txt 14 | 15 | 16 | 17 | Stefan Reuter 18 | http://asterisk-java.org/ 19 | 20 | 2009 21 | 22 | 23 | Wolfgang Pichler 24 | wpichler 25 | 26 | 27 | David Fire 28 | dfire 29 | 30 | 31 | Stefan Reuter 32 | srt 33 | srt at users.sourceforge.net 34 | +1 35 | 36 | 37 | 38 | scm:git:git://github.com/srt/asterisk-java-iax.git 39 | scm:git:git@github.com:srt/asterisk-java-iax.git 40 | 41 | 42 | 43 | reucon 44 | https://nexus.reucon.com/content/repositories/opensource 45 | 46 | 47 | reucon 48 | https://nexus.reucon.com/content/repositories/opensource-snapshots 49 | 50 | 51 | reucon 52 | dav:https://maven.reucon.com/projects/public/${artifactId}/${version} 53 | 54 | 55 | 56 | JIRA 57 | http://jira.reucon.org/browse/AJI 58 | 59 | 60 | 61 | Asterisk-Java User List 62 | http://lists.sourceforge.net/mailman/listinfo/asterisk-java-users 63 | http://lists.sourceforge.net/mailman/listinfo/asterisk-java-users 64 | http://sourceforge.net/mailarchive/forum.php?forum=asterisk-java-users 65 | 66 | 67 | Asterisk-Java Developer List 68 | http://lists.sourceforge.net/mailman/listinfo/asterisk-java-devel 69 | http://lists.sourceforge.net/mailman/listinfo/asterisk-java-devel 70 | http://sourceforge.net/mailarchive/forum.php?forum=asterisk-java-devel 71 | 72 | 73 | 74 | 75 | 76 | maven-compiler-plugin 77 | 78 | 1.6 79 | 1.6 80 | 81 | 82 | 83 | maven-surefire-plugin 84 | 2.4.3 85 | 86 | 87 | maven-release-plugin 88 | 2.2.2 89 | 90 | clean install 91 | true 92 | 93 | 94 | 95 | maven-source-plugin 96 | 2.1 97 | 98 | 99 | attach-sources 100 | 101 | jar 102 | 103 | 104 | 105 | 106 | 107 | org.apache.maven.plugins 108 | maven-jar-plugin 109 | 2.2 110 | 111 | 112 | 113 | org.asteriskjava.iax.ui.BeanCan 114 | 115 | 116 | 117 | 118 | 119 | maven-assembly-plugin 120 | 2.2-beta-4 121 | 122 | 123 | src 124 | bin 125 | 126 | 127 | 128 | 129 | org.codehaus.mojo 130 | cobertura-maven-plugin 131 | 2.2 132 | 133 | 134 | 135 | 136 | org.apache.maven.wagon 137 | wagon-webdav 138 | 1.0-beta-2 139 | 140 | 141 | 142 | 143 | 144 | org.easymock 145 | easymock 146 | 2.5 147 | test 148 | 149 | 150 | junit 151 | junit 152 | 4.6 153 | test 154 | 155 | 156 | 157 | 158 | 159 | maven-javadoc-plugin 160 | 2.5 161 | 162 |
${project.name}
163 |
164 |
165 | 166 | org.codehaus.mojo 167 | cobertura-maven-plugin 168 | 2.2 169 | 170 | 171 | html 172 | xml 173 | 174 | 175 | 176 | 177 | org.codehaus.mojo 178 | jxr-maven-plugin 179 | 2.0-beta-1 180 | 181 | 182 | org.codehaus.mojo 183 | surefire-report-maven-plugin 184 | 2.0-beta-1 185 | 186 | 187 | org.codehaus.mojo 188 | changelog-maven-plugin 189 | 2.0-beta-1 190 | 191 | 192 | org.apache.maven.plugins 193 | maven-pmd-plugin 194 | 2.4 195 | 196 | 1.6 197 | 100 198 | true 199 | 200 | /rulesets/basic.xml 201 | 202 | 203 | 204 | 205 | org.codehaus.mojo 206 | findbugs-maven-plugin 207 | 1.2 208 | 209 | 216 |
217 |
218 | 219 | 220 | release 221 | 222 | 223 | release 224 | 225 | 226 | 227 | 228 | 229 | org.apache.maven.plugins 230 | maven-jar-plugin 231 | 2.2 232 | 233 | 234 | 235 | sign 236 | 237 | 238 | 239 | 240 | 244 | Stefan_Reuter_Code_Signing 245 | true 246 | 250 | 251 | 252 | 253 | org.apache.maven.plugins 254 | maven-gpg-plugin 255 | 1.0-alpha-4 256 | 257 | 258 | sign-artifacts 259 | verify 260 | 261 | sign 262 | 263 | 264 | 265 | 266 | C47292FB 267 | 268 | 269 | 270 | 271 | 272 | 273 |
274 | -------------------------------------------------------------------------------- /readme.txt: -------------------------------------------------------------------------------- 1 | If publication occurs, the following notice shall appear: 2 | Copyright 2005-2007 Mexuar Technologies Ltd. All Rights Reserved. 3 | 4 | Corraleta is a trademark of Mexuar Technologies Ltd. Any unauthorized use 5 | is strictly prohibited. 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . -------------------------------------------------------------------------------- /src/main/java/org/asteriskjava/iax/audio/encodings/gsm/Add.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Mathmatical methods. 3 | * Copyright (C) 1999 Christopher Edwards 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; either version 2 8 | * of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 | * 19 | */ 20 | 21 | package org.asteriskjava.iax.audio.encodings.gsm; 22 | 23 | 24 | public class Add { 25 | public static short saturate(int x) { 26 | return (short) ((x) < Gsm_Def.MIN_WORD ? Gsm_Def.MIN_WORD : 27 | (x) > Gsm_Def.MAX_WORD ? Gsm_Def.MAX_WORD : (x)); 28 | } 29 | 30 | public static short saturate(long x) { 31 | return (short) ((x) < Gsm_Def.MIN_WORD ? Gsm_Def.MIN_WORD : 32 | (x) > Gsm_Def.MAX_WORD ? Gsm_Def.MAX_WORD : (x)); 33 | } 34 | 35 | public static short SASR(int x, int by) { 36 | return (short) ((x) >> (by)); 37 | } 38 | 39 | public static short GSM_ADD(short a, short b) { 40 | /* 41 | * This converts a and b to int implicitely, because 42 | * '+' is not defined for short. 43 | */ 44 | int sum = a + b; 45 | return saturate(sum); 46 | } 47 | 48 | public static short GSM_SUB(short a, short b) { 49 | /* 50 | * This converts a and b to int implicitely, because 51 | * '-' is not defined for short. 52 | */ 53 | int diff = a - b; 54 | return saturate(diff); 55 | } 56 | 57 | public static short GSM_MULT(short a, short b) { 58 | if (a == Gsm_Def.MIN_WORD && b == Gsm_Def.MIN_WORD) { 59 | return Gsm_Def.MAX_WORD; 60 | } else { 61 | return SASR(((int) (a)) * ((int) (b)), 15); 62 | } 63 | } 64 | 65 | public static short GSM_MULT_R(short a, short b) { 66 | if (a == Gsm_Def.MIN_WORD && b == Gsm_Def.MIN_WORD) { 67 | return Gsm_Def.MAX_WORD; 68 | } else { 69 | int prod = (int) (((int) (a)) * ((int) (b)) + 16384); 70 | prod >>= 15; 71 | return (short) (prod & 0xFFFF); 72 | } 73 | } 74 | 75 | 76 | public static short GSM_ABS(short a) { 77 | int b = a < 0 ? (a == Gsm_Def.MIN_WORD ? Gsm_Def.MAX_WORD : -a) : a; 78 | return ((short) (b)); 79 | } 80 | 81 | public static int GSM_L_MULT(short a, short b) 82 | throws IllegalArgumentException { 83 | if (a != Short.MIN_VALUE || b != Short.MIN_VALUE) { 84 | throw new IllegalArgumentException( 85 | "One of the aruments must equal " + Short.MIN_VALUE); 86 | } 87 | return ((int) a * (int) b) << 1; 88 | } 89 | 90 | public static int GSM_L_ADD(int a, int b) { 91 | if (a <= 0) { 92 | if (b >= 0) { 93 | return a + b; 94 | } else { 95 | long A = (long) -(a + 1) + (long) -(b + 1); 96 | return A >= Gsm_Def.MAX_LONGWORD ? Gsm_Def.MIN_LONGWORD : -(int) A - 2; 97 | } 98 | } else if (b <= 0) { 99 | return a + b; 100 | } else { 101 | long A = (long) a + (long) 102 | b; 103 | return (int) (A > Gsm_Def.MAX_LONGWORD ? Gsm_Def.MAX_LONGWORD : A); 104 | } 105 | } 106 | 107 | 108 | /* 109 | * the number of left shifts needed to normalize the 32 bit 110 | * variable L_var1 for positive values on the interval 111 | * 112 | * with minimum of 113 | * minimum of 1073741824 (01000000000000000000000000000000) and 114 | * maximum of 2147483647 (01111111111111111111111111111111) 115 | * 116 | * 117 | * and for negative values on the interval with 118 | * minimum of -2147483648 (-10000000000000000000000000000000) and 119 | * maximum of -1073741824 ( -1000000000000000000000000000000). 120 | * 121 | * in order to normalize the result, the following 122 | * operation must be done: L_norm_var1 = L_var1 << norm( L_var1 ); 123 | * 124 | * (That's 'ffs', only from the left, not the right..) 125 | */ 126 | public static short gsm_norm(int a) 127 | throws IllegalArgumentException { 128 | 129 | if (a == 0) { 130 | throw new IllegalArgumentException 131 | ("gsm_norm: a cannot = 0."); 132 | } 133 | 134 | if (a < 0) { 135 | if (a <= -1073741824) { 136 | return 0; 137 | } 138 | a = ~a; 139 | } 140 | 141 | return (short) (((a & 0xffff0000) != 0) 142 | ? (((a & 0xff000000) != 0) 143 | ? -1 + bitoff[(int) (0xFF & (a >> 24))] 144 | : 7 + bitoff[(int) (0xFF & (a >> 16))]) 145 | : (((a & 0xff00) != 0) 146 | ? 15 + bitoff[(int) (0xFF & (a >> 8))] 147 | : 23 + bitoff[(int) (0xFF & a)])); 148 | } 149 | 150 | 151 | public static short gsm_asl(short a, int n) { 152 | if (n >= 16) return ((short) 0); 153 | 154 | if (n <= -16) 155 | if (a < 0) 156 | return (short) -1; 157 | else 158 | return (short) -0; 159 | 160 | if (n < 0) return gsm_asr(a, -n); 161 | 162 | return ((short) (a << n)); 163 | } 164 | 165 | public static short gsm_asr(short a, int n) { 166 | if (n >= 16) 167 | if (a < 0) 168 | return (short) -1; 169 | else 170 | return (short) -0; 171 | if (n <= -16) return ((short) 0); 172 | if (n < 0) return ((short) (a << -n)); 173 | 174 | return ((short) (a >> n)); 175 | } 176 | 177 | 178 | public static short gsm_div(short num, short denum) 179 | throws IllegalArgumentException { 180 | 181 | int L_num = num; 182 | int L_denum = denum; 183 | short div = 0; 184 | int k = 15; 185 | 186 | /* The parameter num sometimes becomes zero. 187 | * Although this is explicitly guarded against in 4.2.5, 188 | * we assume that the result should then be zero as well. 189 | */ 190 | 191 | /* assert(num != 0); */ 192 | 193 | if (!(num >= 0 && denum >= num)) { 194 | throw new IllegalArgumentException 195 | ("gsm_div: num >= 0 && denum >= num"); 196 | } 197 | 198 | if (num == 0) 199 | return 0; 200 | 201 | while (k != 0) { 202 | k--; 203 | div <<= 1; 204 | L_num <<= 1; 205 | 206 | if (L_num >= L_denum) { 207 | L_num -= L_denum; 208 | div++; 209 | } 210 | } 211 | return div; 212 | } 213 | 214 | 215 | private static final short bitoff[] = 216 | { 217 | 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 218 | 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 219 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 220 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 221 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 222 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 223 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 224 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 225 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 226 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 233 | }; 234 | 235 | } 236 | 237 | -------------------------------------------------------------------------------- /src/main/java/org/asteriskjava/iax/audio/encodings/gsm/Gsm_Def.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Static defines. 3 | * Copyright (C) 1999 Christopher Edwards 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; either version 2 8 | * of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 | * 19 | */ 20 | 21 | package org.asteriskjava.iax.audio.encodings.gsm; 22 | 23 | public abstract class Gsm_Def { 24 | // TODO: remove 25 | // Define the magic number for audio files 26 | public static final int AUDIO_FILE_MAGIC = 0x2e736e64; 27 | 28 | // TODO: remove 29 | // The encoding key for type: 8-bit ISDN u-law 30 | public static final int AUDIO_FILE_ENCODING_MULAW_8 = 1; 31 | 32 | public static final short FRAME_SIZE = 33; 33 | public static final short MAX_FRAME_READ = 1000; 34 | 35 | // TODO: use Short.MIN/MAX_VALUE 36 | public static final short MIN_WORD = -32768; 37 | public static final short MAX_WORD = 32767; 38 | 39 | // TODO: use Integer.MIN/MAX_VALUE 40 | public static final int MIN_LONGWORD = -2147483648; 41 | public static final int MAX_LONGWORD = 2147483647; 42 | 43 | /* Table 4.1 Quantization of the Log.-Area Ratios 44 | */ 45 | /* i 1 2 3 4 5 6 7 8 */ 46 | 47 | public static final short gsm_A[] = 48 | { 49 | 20480, 20480, 20480, 20480, 13964, 15360, 8534, 9036 50 | }; 51 | 52 | public static final short gsm_B[] = 53 | { 54 | 0, 0, 2048, -2560, 94, -1792, -341, -1144 55 | }; 56 | 57 | public static final short gsm_MIC[] = 58 | { 59 | -32, -32, -16, -16, -8, -8, -4, -4 60 | }; 61 | 62 | public static final short gsm_MAC[] = 63 | { 64 | 31, 31, 15, 15, 7, 7, 3, 3 65 | }; 66 | 67 | /* Table 4.2 Tabulation of 1/A[1..8] 68 | */ 69 | public static final short gsm_INVA[] = 70 | { 71 | 13107, 13107, 13107, 13107, 19223, 17476, 31454, 29708 72 | }; 73 | 74 | /* Table 4.3a Decision level of the LTP gain quantizer 75 | */ 76 | /* bc 0 1 2 3 */ 77 | public static final short gsm_DLB[] = 78 | { 79 | 6554, 16384, 26214, 32767 80 | }; 81 | 82 | 83 | /* Table 4.3b Quantization levels of the LTP gain quantizer 84 | */ 85 | /* bc 0 1 2 3 */ 86 | public static final short gsm_QLB[] = 87 | { 88 | 3277, 11469, 21299, 32767 89 | }; 90 | 91 | 92 | /* Table 4.4 Coefficients of the weighting filter 93 | */ 94 | /* i 0 1 2 3 4 5 6 7 8 9 10 */ 95 | public static final short gsm_H[] = 96 | { 97 | -134, -374, 0, 2054, 5741, 8192, 5741, 2054, 0, -374, -134 98 | }; 99 | 100 | 101 | /* Table 4.5 Normalized inverse mantissa used to compute xM/xmax 102 | */ 103 | /* i 0 1 2 3 4 5 6 7 */ 104 | public static final short gsm_NRFAC[] = 105 | { 106 | 29128, 26215, 23832, 21846, 20165, 18725, 17476, 16384 107 | }; 108 | 109 | 110 | /* Table 4.6 Normalized direct mantissa used to compute xM/xmax 111 | */ 112 | /* i 0 1 2 3 4 5 6 7 */ 113 | public static final short gsm_FAC[] = 114 | { 115 | 18431, 20479, 22527, 24575, 26623, 28671, 30719, 32767 116 | }; 117 | } 118 | -------------------------------------------------------------------------------- /src/main/java/org/asteriskjava/iax/audio/encodings/gsm/Gsm_State.java: -------------------------------------------------------------------------------- 1 | /* 2 | * State control for encoding. 3 | * Copyright (C) 1999 Christopher Edwards 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; either version 2 8 | * of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 | * 19 | */ 20 | 21 | package org.asteriskjava.iax.audio.encodings.gsm; 22 | 23 | 24 | public class Gsm_State { 25 | private short[] dp0; 26 | private short z1; /* preprocessing, Offset_com. */ 27 | private int L_z2; /* Offset_com. */ 28 | private int mp; /* Preemphasis */ 29 | 30 | private short[] u; /* short_term.java */ 31 | private short[][] LARpp; /* */ 32 | private short j; /* */ 33 | 34 | private short nrp; /* long_term.java, synthesis */ 35 | private short[] v; /* short_term.java, synthesis */ 36 | private short msr; /* Gsm_Decoder.java, Postprocessing */ 37 | 38 | 39 | public Gsm_State() { 40 | short Dp0[] = new short[280]; 41 | short U[] = new short[8]; 42 | short LARpp[][] = new short[2][8]; 43 | short V[] = new short[9]; 44 | 45 | this.setDp0(Dp0); 46 | this.setZ1((short) 0); 47 | this.setL_z2(0); 48 | this.setMp(0); 49 | this.setU(U); 50 | this.setLARpp(LARpp); 51 | this.setJ((short) 0); 52 | this.setNrp((short) 40); 53 | this.setV(V); 54 | this.setMsr((short) 0); 55 | } 56 | 57 | 58 | public void dump_Gsm_State() { 59 | int i, col; 60 | 61 | System.out.println("\ndp0[]: "); 62 | /*for(i = 0; i < dp0.length; ++i) { 63 | System.out.print("["+i+"] "+dp0[i]); 64 | if (i < dp0.length - 1) 65 | System.out.print(", "); 66 | }*/ 67 | System.out.println("\nz1: " + z1); 68 | System.out.println("\nL_z2: " + L_z2); 69 | System.out.println("\nmp: " + mp); 70 | System.out.println("\nu[]: "); 71 | for (i = 0; i < u.length; ++i) { 72 | System.out.print("[" + i + "] " + u[i]); 73 | if (i < u.length - 1) 74 | System.out.print(", "); 75 | } 76 | System.out.print("\n"); 77 | System.out.println("\nLARpp[]: "); 78 | for (i = 0; i < 2; ++i) { 79 | for (col = 0; col < 8; ++col) { 80 | System.out.print("[" + i + "][" + col + "] " + LARpp[i][col]); 81 | System.out.print(", "); 82 | } 83 | System.out.print("\n"); 84 | } 85 | System.out.print("\n"); 86 | System.out.println("\nj: " + j); 87 | System.out.println("\nnrp: " + nrp); 88 | System.out.println("\nv[]: "); 89 | for (i = 0; i < v.length; ++i) { 90 | System.out.print("[" + i + "] " + v[i]); 91 | if (i < v.length - 1) 92 | System.out.print(", "); 93 | } 94 | System.out.print("\n"); 95 | System.out.println("\nmsr: " + msr); 96 | //System.out.println("\nverbose: " + verbose); 97 | //System.out.println("\nfast: " + fast); 98 | } 99 | 100 | 101 | public String toString() { 102 | String temp = new String(""); 103 | return (new String("").valueOf(nrp)); 104 | } 105 | 106 | public void setDp0(short[] lcl_arg0) { 107 | dp0 = lcl_arg0; 108 | } 109 | 110 | 111 | public void setDp0Indexed(int ix, short lcl_arg0) { 112 | dp0[ix] = lcl_arg0; 113 | } 114 | 115 | 116 | public short[] getDp0() { 117 | return dp0; 118 | } 119 | 120 | 121 | public short getDp0Indexed(int ix) { 122 | return dp0[ix]; 123 | } 124 | 125 | 126 | public void setZ1(short lcl_arg0) { 127 | z1 = lcl_arg0; 128 | } 129 | 130 | 131 | public short getZ1() { 132 | return z1; 133 | } 134 | 135 | 136 | public void setL_z2(int lcl_arg0) { 137 | L_z2 = lcl_arg0; 138 | } 139 | 140 | 141 | public int getL_z2() { 142 | return L_z2; 143 | } 144 | 145 | 146 | public void setMp(int lcl_arg0) { 147 | mp = lcl_arg0; 148 | } 149 | 150 | 151 | public int getMp() { 152 | return mp; 153 | } 154 | 155 | 156 | public void setU(short[] lcl_arg0) { 157 | u = lcl_arg0; 158 | } 159 | 160 | 161 | public void setUIndexed(int ix, short lcl_arg0) { 162 | u[ix] = lcl_arg0; 163 | } 164 | 165 | 166 | public short[] getU() { 167 | return u; 168 | } 169 | 170 | 171 | public short getUIndexed(int ix) { 172 | return u[ix]; 173 | } 174 | 175 | 176 | public void setLARpp(short[][] lcl_arg0) { 177 | LARpp = lcl_arg0; 178 | } 179 | 180 | 181 | public void setLARppIndexed(int ix, short[] lcl_arg0) { 182 | LARpp[ix] = lcl_arg0; 183 | } 184 | 185 | 186 | public short[][] getLARpp() { 187 | return LARpp; 188 | } 189 | 190 | 191 | public short[] getLARppIndexed(int ix) { 192 | return LARpp[ix]; 193 | } 194 | 195 | 196 | public void setJ(short lcl_arg0) { 197 | j = lcl_arg0; 198 | } 199 | 200 | 201 | public short getJ() { 202 | return j; 203 | } 204 | 205 | 206 | public void setNrp(short lcl_arg0) { 207 | nrp = lcl_arg0; 208 | } 209 | 210 | 211 | public short getNrp() { 212 | return nrp; 213 | } 214 | 215 | 216 | public void setV(short[] lcl_arg0) { 217 | v = lcl_arg0; 218 | } 219 | 220 | 221 | public void setVIndexed(int ix, short lcl_arg0) { 222 | v[ix] = lcl_arg0; 223 | } 224 | 225 | 226 | public short[] getV() { 227 | return v; 228 | } 229 | 230 | 231 | public short getVIndexed(int ix) { 232 | return v[ix]; 233 | } 234 | 235 | 236 | public void setMsr(short lcl_arg0) { 237 | msr = lcl_arg0; 238 | } 239 | 240 | 241 | public short getMsr() { 242 | return msr; 243 | } 244 | } 245 | -------------------------------------------------------------------------------- /src/main/java/org/asteriskjava/iax/audio/encodings/gsm/InvalidGSMFrameException.java: -------------------------------------------------------------------------------- 1 | // $Id: InvalidGSMFrameException.java,v 1.1 2000/08/10 17:47:08 pfisterer Exp $ 2 | 3 | // This file is part of the GSM 6.10 audio decoder library for Java 4 | // Copyright (C) 1998 Steven Pickles (pix@test.at) 5 | 6 | // This library is free software; you can redistribute it and/or 7 | // modify it under the terms of the GNU Library General Public 8 | // License as published by the Free Software Foundation; either 9 | // version 2 of the License, or (at your option) any later version. 10 | 11 | // This library is distributed in the hope that it will be useful, 12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | // Library General Public License for more details. 15 | 16 | // You should have received a copy of the GNU Library General Public 17 | // License along with this library; if not, write to the Free 18 | // Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 | 20 | 21 | // This software is a port of the GSM Library provided by 22 | // Jutta Degener (jutta@cs.tu-berlin.de) and 23 | // Carsten Bormann (cabo@cs.tu-berlin.de), 24 | // Technische Universitaet Berlin 25 | 26 | package org.asteriskjava.iax.audio.encodings.gsm; 27 | 28 | 29 | public class InvalidGSMFrameException 30 | extends Exception { 31 | } 32 | 33 | 34 | /*** InvalidGSMFrameException.java ***/ 35 | -------------------------------------------------------------------------------- /src/main/java/org/asteriskjava/iax/audio/encodings/gsm/Lpc.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Lpc port to Java. 3 | * Copyright (C) 1999 Christopher Edwards 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; either version 2 8 | * of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 | * 19 | */ 20 | 21 | package org.asteriskjava.iax.audio.encodings.gsm; 22 | 23 | public class Lpc { 24 | private int L_ACF[] = new int[9]; 25 | 26 | 27 | public void Gsm_LPC_Analysis( 28 | short[] so, /* 0..159 signals IN/OUT */ 29 | short[] LARc) /* 0..7 LARc's OUT */ { 30 | Autocorrelation(so); 31 | Reflection_coefficients(LARc); 32 | Transformation_to_Log_Area_Ratios(LARc); 33 | Quantization_and_coding(LARc); 34 | } 35 | 36 | 37 | private void Autocorrelation(short[] so) /* [0..159] IN/OUT */ 38 | throws IllegalArgumentException { 39 | int i = 0, sp_index = 0; 40 | short temp = 0, smax = 0, scalauto = 0; 41 | int L_temp = 0; 42 | int L_temp2 = 0; 43 | 44 | /* Dynamic scaling of the array s[0..159] 45 | */ 46 | 47 | /* Search for the maximum. 48 | */ 49 | for (int k = 0; k <= 159; k++) { 50 | temp = Add.GSM_ADD(so[k], (short) 0); 51 | if (temp > smax) smax = temp; 52 | } 53 | 54 | /* Computation of the scaling factor. 55 | */ 56 | if (smax == 0) { 57 | scalauto = 0; 58 | } else { 59 | if (!(smax > 0)) { 60 | throw new IllegalArgumentException 61 | ("Autocorrelation: smax = " 62 | + smax + " should be > 0."); 63 | } 64 | scalauto = (short) 65 | (4 - Add.gsm_norm((int) (smax << 16))); /* sub(4,..) */ 66 | } 67 | 68 | /* Scaling of the array s[0...159] 69 | */ 70 | 71 | if (scalauto > 0) { 72 | if (!(scalauto <= 4)) { 73 | throw new IllegalArgumentException 74 | ("Autocorrelation: scalauto = " 75 | + scalauto + " should be <= 4."); 76 | } 77 | switch (scalauto) { 78 | case 1: 79 | for (int k = 0; k <= 159; k++) { 80 | so[k] = Add.GSM_MULT_R(so[k], (short) 16384); 81 | } 82 | break; 83 | 84 | case 2: 85 | for (int k = 0; k <= 159; k++) { 86 | so[k] = Add.GSM_MULT_R(so[k], 87 | (short) (16384 >> 1)); 88 | } 89 | break; 90 | 91 | case 3: 92 | for (int k = 0; k <= 159; k++) { 93 | so[k] = Add.GSM_MULT_R(so[k], 94 | (short) (16384 >> 2)); 95 | } 96 | break; 97 | 98 | case 4: 99 | for (int k = 0; k <= 159; k++) { 100 | so[k] = Add.GSM_MULT_R(so[k], 101 | (short) (16384 >> 3)); 102 | } 103 | break; 104 | } 105 | } 106 | 107 | /* Compute the L_ACF[..]. 108 | */ 109 | short[] sp = so; 110 | short sl = sp[sp_index]; 111 | 112 | // Zero out L_ACF 113 | int[] temp_arr = {0, 0, 0, 0, 0, 0, 0, 0, 0}; 114 | System.arraycopy(temp_arr, 0, L_ACF, 0, L_ACF.length); 115 | 116 | L_ACF[0] += (int) (sl * sp[(sp_index - 0)]); 117 | 118 | sl = sp[++sp_index]; 119 | L_ACF[0] += (int) (sl * sp[(sp_index - 0)]); 120 | L_ACF[1] += (int) (sl * sp[(sp_index - 1)]); 121 | 122 | sl = sp[++sp_index]; 123 | L_ACF[0] += (int) (sl * sp[(sp_index - 0)]); 124 | L_ACF[1] += (int) (sl * sp[(sp_index - 1)]); 125 | L_ACF[2] += (int) (sl * sp[(sp_index - 2)]); 126 | 127 | sl = sp[++sp_index]; 128 | L_ACF[0] += (int) (sl * sp[(sp_index - 0)]); 129 | L_ACF[1] += (int) (sl * sp[(sp_index - 1)]); 130 | L_ACF[2] += (int) (sl * sp[(sp_index - 2)]); 131 | L_ACF[3] += (int) (sl * sp[(sp_index - 3)]); 132 | 133 | sl = sp[++sp_index]; 134 | L_ACF[0] += (int) (sl * sp[(sp_index - 0)]); 135 | L_ACF[1] += (int) (sl * sp[(sp_index - 1)]); 136 | L_ACF[2] += (int) (sl * sp[(sp_index - 2)]); 137 | L_ACF[3] += (int) (sl * sp[(sp_index - 3)]); 138 | L_ACF[4] += (int) (sl * sp[(sp_index - 4)]); 139 | 140 | sl = sp[++sp_index]; 141 | L_ACF[0] += (int) (sl * sp[(sp_index - 0)]); 142 | L_ACF[1] += (int) (sl * sp[(sp_index - 1)]); 143 | L_ACF[2] += (int) (sl * sp[(sp_index - 2)]); 144 | L_ACF[3] += (int) (sl * sp[(sp_index - 3)]); 145 | L_ACF[4] += (int) (sl * sp[(sp_index - 4)]); 146 | L_ACF[5] += (int) (sl * sp[(sp_index - 5)]); 147 | 148 | sl = sp[++sp_index]; 149 | L_ACF[0] += (int) (sl * sp[(sp_index - 0)]); 150 | L_ACF[1] += (int) (sl * sp[(sp_index - 1)]); 151 | L_ACF[2] += (int) (sl * sp[(sp_index - 2)]); 152 | L_ACF[3] += (int) (sl * sp[(sp_index - 3)]); 153 | L_ACF[4] += (int) (sl * sp[(sp_index - 4)]); 154 | L_ACF[5] += (int) (sl * sp[(sp_index - 5)]); 155 | L_ACF[6] += (int) (sl * sp[(sp_index - 6)]); 156 | 157 | sl = sp[++sp_index]; 158 | L_ACF[0] += (int) (sl * sp[(sp_index - 0)]); 159 | L_ACF[1] += (int) (sl * sp[(sp_index - 1)]); 160 | L_ACF[2] += (int) (sl * sp[(sp_index - 2)]); 161 | L_ACF[3] += (int) (sl * sp[(sp_index - 3)]); 162 | L_ACF[4] += (int) (sl * sp[(sp_index - 4)]); 163 | L_ACF[5] += (int) (sl * sp[(sp_index - 5)]); 164 | L_ACF[6] += (int) (sl * sp[(sp_index - 6)]); 165 | L_ACF[7] += (int) (sl * sp[(sp_index - 7)]); 166 | 167 | sl = sp[++sp_index]; 168 | 169 | for (i = sp_index; i < 160; ++i) { 170 | 171 | sl = sp[i]; 172 | 173 | L_ACF[0] += (int) (sl * sp[(i - 0)]); 174 | L_ACF[1] += (int) (sl * sp[(i - 1)]); 175 | L_ACF[2] += (int) (sl * sp[(i - 2)]); 176 | L_ACF[3] += (int) (sl * sp[(i - 3)]); 177 | L_ACF[4] += (int) (sl * sp[(i - 4)]); 178 | L_ACF[5] += (int) (sl * sp[(i - 5)]); 179 | L_ACF[6] += (int) (sl * sp[(i - 6)]); 180 | L_ACF[7] += (int) (sl * sp[(i - 7)]); 181 | L_ACF[8] += (int) (sl * sp[(i - 8)]); 182 | } 183 | 184 | for (int k = 0; k < 9; k++) { 185 | L_ACF[k] <<= 1; 186 | } 187 | 188 | /* Rescaling of the array s[0..159] 189 | */ 190 | if (scalauto > 0) { 191 | if (!(scalauto <= 4)) { 192 | throw new IllegalArgumentException 193 | ("Autocorrelation: scalauto = " 194 | + scalauto + " should be <= 4."); 195 | } 196 | 197 | for (int k = 0; k < 160; k++) { 198 | so[k] <<= scalauto; 199 | } 200 | } 201 | } 202 | 203 | 204 | private void Reflection_coefficients(short[] r /* 0...7 OUT */) 205 | throws IllegalArgumentException { 206 | short temp = 0; 207 | int ltmp = 0; 208 | int r_index = 0; 209 | 210 | short[] ACF = new short[9]; /* 0..8 */ 211 | short[] P = new short[9]; /* 0..8 */ 212 | short[] K = new short[9]; /* 2..8 */ 213 | 214 | /* Schur recursion with 16 bits arithmetic. 215 | */ 216 | 217 | if (L_ACF[0] == 0) { /* everything is the same. */ 218 | for (int i = 0; i < 8; i++) { 219 | r[i] = 0; 220 | } 221 | return; 222 | } 223 | 224 | if (L_ACF[0] == 0) { 225 | throw new IllegalArgumentException 226 | ("Reflection_coefficients: L_ACF[0] = " 227 | + L_ACF[0] + " should not = 0."); 228 | } 229 | 230 | temp = Add.gsm_norm(L_ACF[0]); 231 | 232 | if (!(temp >= 0 && temp < 32)) { 233 | throw new IllegalArgumentException 234 | ("Reflection_coefficients: temp = " 235 | + temp + " should be >= 0 and < 32."); 236 | } 237 | 238 | 239 | /* ? overflow ? */ 240 | for (int i = 0; i <= 8; i++) { 241 | ACF[i] = Add.SASR(L_ACF[i] << temp, 16); 242 | } 243 | 244 | /* Initialize array P[..] and K[..] for the recursion. 245 | */ 246 | 247 | System.arraycopy(ACF, 0, K, 0, 7); 248 | 249 | System.arraycopy(ACF, 0, P, 0, 8); 250 | 251 | /* Compute reflection coefficients 252 | */ 253 | for (int n = 1; n <= 8; n++, r_index++) { 254 | 255 | temp = P[1]; 256 | temp = Add.GSM_ABS(temp); 257 | if (P[0] < temp) { 258 | for (int i = n; i < 8; i++) { 259 | r[i] = 0; 260 | } 261 | return; 262 | } 263 | 264 | r[r_index] = Add.gsm_div(temp, P[0]); 265 | 266 | if (!(r[r_index] >= 0)) { 267 | throw new IllegalArgumentException 268 | ("Reflection_coefficients: r[" + r_index + "] = " 269 | + r[r_index] + " should be >= 0"); 270 | } 271 | 272 | if (P[1] > 0) { 273 | /* r[n] = sub(0, r[n]) */ 274 | r[r_index] = (short) (-(r[r_index])); 275 | } 276 | 277 | if (r[r_index] == Gsm_Def.MIN_WORD) { 278 | throw new IllegalArgumentException 279 | ("Reflection_coefficients: r[" + r_index + "] = " 280 | + r[r_index] + " should not be " + Gsm_Def.MIN_WORD); 281 | } 282 | if (n == 8) 283 | return; 284 | 285 | /* Schur recursion 286 | */ 287 | temp = Add.GSM_MULT_R(P[1], r[r_index]); 288 | P[0] = Add.GSM_ADD(P[0], temp); 289 | 290 | for (int m = 1; m <= 8 - n; m++) { 291 | temp = Add.GSM_MULT_R(K[m], r[r_index]); 292 | P[m] = Add.GSM_ADD(P[m + 1], temp); 293 | 294 | temp = Add.GSM_MULT_R(P[m + 1], r[r_index]); 295 | K[m] = Add.GSM_ADD(K[m], temp); 296 | } 297 | } 298 | } 299 | 300 | 301 | 302 | /* 4.2.6 */ 303 | 304 | /* 305 | * The following scaling for r[..] and LAR[..] has been used: 306 | * 307 | * r[..] = integer( real_r[..]*32768. ); -1 <= real_r < 1. 308 | * LAR[..] = integer( real_LAR[..] * 16384 ); 309 | * with -1.625 <= real_LAR <= 1.625 310 | */ 311 | private void Transformation_to_Log_Area_Ratios(short[] r /* 0..7 IN/OUT */) 312 | throws IllegalArgumentException { 313 | short temp; 314 | 315 | /* Computation of the LAR[0..7] from the r[0..7] 316 | */ 317 | for (int i = 0; i < 8; i++) { 318 | 319 | temp = r[i]; 320 | temp = Add.GSM_ABS(temp); 321 | 322 | if (!(temp >= 0)) { 323 | throw new IllegalArgumentException 324 | ("Transformation_to_Log_Area_Ratios: temp = " 325 | + temp + " should be >= 0 "); 326 | } 327 | 328 | if (temp < 22118) { 329 | temp >>= 1; 330 | } else if (temp < 31130) { 331 | 332 | if (!(temp >= 11059)) { 333 | throw new IllegalArgumentException 334 | ("Transformation_to_Log_Area_Ratios: temp = " 335 | + temp + " should be >= 11059 "); 336 | } 337 | 338 | temp -= 11059; 339 | } else { 340 | if (!(temp >= 26112)) { 341 | throw new IllegalArgumentException 342 | ("Transformation_to_Log_Area_Ratios: temp = " 343 | + temp + " should be >= 26112 "); 344 | } 345 | 346 | temp -= 26112; 347 | temp <<= 2; 348 | } 349 | 350 | r[i] = (short) (r[i] < 0 ? -temp : temp); 351 | 352 | if (r[i] == Gsm_Def.MIN_WORD) { 353 | throw new IllegalArgumentException 354 | ("Transformation_to_Log_Area_Ratios: r[" + i + "] = " 355 | + r[i] + " should not be = " + Gsm_Def.MIN_WORD); 356 | } 357 | } 358 | } 359 | 360 | 361 | 362 | /* 4.2.7 */ 363 | 364 | /* This procedure needs four tables; the following equations 365 | * give the optimum scaling for the constants: 366 | * 367 | * A[0..7] = integer( real_A[0..7] * 1024 ) 368 | * B[0..7] = integer( real_B[0..7] * 512 ) 369 | * MAC[0..7] = maximum of the LARc[0..7] 370 | * MIC[0..7] = minimum of the LARc[0..7] 371 | */ 372 | private void Quantization_and_coding(short[] LAR /* [0..7] IN/OUT */) { 373 | int index = 0; 374 | 375 | STEP2(20480, 0, 31, -32, LAR, index++); 376 | STEP2(20480, 0, 31, -32, LAR, index++); 377 | STEP2(20480, 2048, 15, -16, LAR, index++); 378 | STEP2(20480, -2560, 15, -16, LAR, index++); 379 | 380 | STEP2(13964, 94, 7, -8, LAR, index++); 381 | STEP2(15360, -1792, 7, -8, LAR, index++); 382 | STEP2(8534, -341, 3, -4, LAR, index++); 383 | STEP2(9036, -1144, 3, -4, LAR, index++); 384 | 385 | } 386 | 387 | 388 | private void STEP2(int A, int B, int MAC, int MIC, 389 | short[] LAR, int index) { 390 | short temp = 0; 391 | 392 | temp = Add.GSM_MULT((short) A, LAR[index]); 393 | temp = Add.GSM_ADD(temp, (short) B); 394 | temp = Add.GSM_ADD(temp, (short) 256); 395 | temp = Add.SASR(temp, 9); 396 | LAR[index] = (short) (temp > MAC ? MAC - MIC : 397 | (temp < MIC ? 0 : temp - MIC)); 398 | } 399 | } 400 | -------------------------------------------------------------------------------- /src/main/java/org/asteriskjava/iax/audio/encodings/gsm/Short_term.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Short term port to Java. 3 | * Copyright (C) 1999 Christopher Edwards 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; either version 2 8 | * of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 | * 19 | */ 20 | 21 | package org.asteriskjava.iax.audio.encodings.gsm; 22 | 23 | public class Short_term { 24 | public void Gsm_Short_Term_Analysis_Filter( 25 | Gsm_State S, 26 | short[] LARc, /* coded log area ratio [0..7] IN */ 27 | short[] s /* signal [0..159] IN/OUT */ 28 | ) 29 | throws ArrayIndexOutOfBoundsException { 30 | short[] LARp = new short[8]; 31 | 32 | int array_index0 = S.getJ(); 33 | int array_index1 = array_index0; 34 | 35 | array_index1 ^= 1; 36 | S.setJ((short) array_index1); 37 | 38 | if (array_index0 < 0 || array_index0 > 1 || 39 | array_index1 < 0 || array_index1 > 1) { 40 | throw new ArrayIndexOutOfBoundsException 41 | ("Gsm_Short_Term_Synthesis_Filter: Indexing LARpp " 42 | + "incorrectly. Should be >= 0 and <= 1"); 43 | } 44 | 45 | short[] LARpp_j = S.getLARppIndexed(array_index0); 46 | short[] LARpp_j_1 = S.getLARppIndexed(array_index1); 47 | 48 | Decoding_of_the_coded_Log_Area_Ratios(LARc, LARpp_j); 49 | 50 | Coefficients_0_12(LARpp_j_1, LARpp_j, LARp); 51 | LARp_to_rp(LARp); 52 | Short_term_analysis_filtering(S, LARp, 13, s, 0); 53 | 54 | Coefficients_13_26(LARpp_j_1, LARpp_j, LARp); 55 | LARp_to_rp(LARp); 56 | Short_term_analysis_filtering(S, LARp, 14, s, 13); 57 | 58 | Coefficients_27_39(LARpp_j_1, LARpp_j, LARp); 59 | LARp_to_rp(LARp); 60 | Short_term_analysis_filtering(S, LARp, 13, s, 27); 61 | 62 | Coefficients_40_159(LARpp_j, LARp); 63 | LARp_to_rp(LARp); 64 | Short_term_analysis_filtering(S, LARp, 120, s, 40); 65 | } 66 | 67 | 68 | public void Gsm_Short_Term_Synthesis_Filter( 69 | Gsm_State S, 70 | short[] LARcr, /* received log area ratios [0..7] IN */ 71 | short[] wt, /* received d [0..159] IN */ 72 | int[] s /* signal s [0..159] OUT */ 73 | ) 74 | throws ArrayIndexOutOfBoundsException { 75 | short[] LARp = new short[8]; 76 | 77 | int array_index0 = S.getJ(); 78 | int array_index1 = array_index0; 79 | 80 | array_index1 ^= 1; 81 | S.setJ((short) array_index1); 82 | 83 | if (array_index0 < 0 || array_index0 > 1 || 84 | array_index1 < 0 || array_index1 > 1) { 85 | throw new ArrayIndexOutOfBoundsException 86 | ("Gsm_Short_Term_Synthesis_Filter: Indexing LARpp " 87 | + "incorrectly. Should be >= 0 and <= 1"); 88 | } 89 | 90 | short[] LARpp_j = S.getLARppIndexed(array_index0); 91 | short[] LARpp_j_1 = S.getLARppIndexed(array_index1); 92 | 93 | Decoding_of_the_coded_Log_Area_Ratios(LARcr, LARpp_j); 94 | 95 | Coefficients_0_12(LARpp_j_1, LARpp_j, LARp); 96 | LARp_to_rp(LARp); 97 | Short_term_synthesis_filtering(S, LARp, 13, wt, s, 0); 98 | 99 | Coefficients_13_26(LARpp_j_1, LARpp_j, LARp); 100 | LARp_to_rp(LARp); 101 | Short_term_synthesis_filtering(S, LARp, 14, wt, s, 13); 102 | 103 | Coefficients_27_39(LARpp_j_1, LARpp_j, LARp); 104 | LARp_to_rp(LARp); 105 | Short_term_synthesis_filtering(S, LARp, 13, wt, s, 27); 106 | 107 | Coefficients_40_159(LARpp_j, LARp); 108 | LARp_to_rp(LARp); 109 | Short_term_synthesis_filtering(S, LARp, 120, wt, s, 40); 110 | 111 | S.setLARppIndexed(array_index0, LARpp_j); 112 | S.setLARppIndexed(array_index1, LARpp_j_1); 113 | } 114 | 115 | 116 | public static void Decoding_of_the_coded_Log_Area_Ratios( 117 | short[] LARc, /* coded log area ratio [0..7] IN */ 118 | short[] LARpp) /* out: decoded .. */ { 119 | short temp1 = 0, temp2 = 0; 120 | int index = 0; 121 | 122 | /* This procedure requires for efficient implementation 123 | * two tables. 124 | * 125 | * INVA[1..8] = integer( (32768 * 8) / real_A[1..8]) 126 | * MIC[1..8] = minimum value of the LARc[1..8] 127 | */ 128 | 129 | /* Compute the LARpp[1..8] 130 | */ 131 | 132 | STEP(LARc, LARpp, index++, temp1, (short) 0, (short) -32, (short) 13107); 133 | STEP(LARc, LARpp, index++, temp1, (short) 0, (short) -32, (short) 13107); 134 | STEP(LARc, LARpp, index++, temp1, (short) 2048, (short) -16, (short) 13107); 135 | STEP(LARc, LARpp, index++, temp1, (short) -2560, (short) -16, (short) 13107); 136 | 137 | STEP(LARc, LARpp, index++, temp1, (short) 94, (short) -8, (short) 19223); 138 | STEP(LARc, LARpp, index++, temp1, (short) -1792, (short) -8, (short) 17476); 139 | STEP(LARc, LARpp, index++, temp1, (short) -341, (short) -4, (short) 31454); 140 | STEP(LARc, LARpp, index++, temp1, (short) -1144, (short) -4, (short) 29708); 141 | 142 | /* NOTE: the addition of *MIC is used to restore 143 | * the sign of *LARc. 144 | */ 145 | } 146 | 147 | 148 | public static void STEP(short[] LARc, short[] LARpp, int index, 149 | short temp1, short B, short MIC, short INVA) { 150 | temp1 = (short) (Add.GSM_ADD(LARc[index], MIC) << 10); 151 | temp1 = Add.GSM_SUB(temp1, (short) (B << 1)); 152 | temp1 = Add.GSM_MULT_R(INVA, temp1); 153 | LARpp[index] = Add.GSM_ADD(temp1, temp1); 154 | } 155 | 156 | 157 | 158 | /* 4.2.9 */ 159 | /* Computation of the quantized reflection coefficients 160 | */ 161 | 162 | /* 4.2.9.1 Interpolation of the LARpp[1..8] to get the LARp[1..8] 163 | */ 164 | 165 | /* 166 | * Within each frame of 160 analyzed speech samples the short term 167 | * analysis and synthesis filters operate with four different sets of 168 | * coefficients, derived from the previous set of decoded LARs(LARpp(j-1)) 169 | * and the actual set of decoded LARs (LARpp(j)) 170 | * 171 | * (Initial value: LARpp(j-1)[1..8] = 0.) 172 | */ 173 | public static void Coefficients_0_12( 174 | short[] LARpp_j_1, 175 | short[] LARpp_j, 176 | short[] LARp) { 177 | for (int i = 0; i < 8; i++) { 178 | LARp[i] = Add.GSM_ADD(Add.SASR(LARpp_j_1[i], 2), 179 | Add.SASR(LARpp_j[i], 2)); 180 | 181 | LARp[i] = Add.GSM_ADD(LARp[i], 182 | Add.SASR(LARpp_j_1[i], 1)); 183 | } 184 | } 185 | 186 | 187 | public static void Coefficients_13_26( 188 | short[] LARpp_j_1, 189 | short[] LARpp_j, 190 | short[] LARp) { 191 | for (int i = 0; i < 8; i++) { 192 | LARp[i] = Add.GSM_ADD(Add.SASR(LARpp_j_1[i], 1), 193 | Add.SASR(LARpp_j[i], 1)); 194 | } 195 | } 196 | 197 | 198 | public static void Coefficients_27_39( 199 | short[] LARpp_j_1, 200 | short[] LARpp_j, 201 | short[] LARp) { 202 | for (int i = 0; i < 8; i++) { 203 | LARp[i] = Add.GSM_ADD(Add.SASR(LARpp_j_1[i], 2), 204 | Add.SASR(LARpp_j[i], 2)); 205 | 206 | LARp[i] = Add.GSM_ADD(LARp[i], 207 | Add.SASR(LARpp_j[i], 1)); 208 | } 209 | } 210 | 211 | 212 | public static void Coefficients_40_159( 213 | short[] LARpp_j, 214 | short[] LARp) { 215 | for (int i = 0; i < 8; i++) 216 | LARp[i] = LARpp_j[i]; 217 | } 218 | 219 | 220 | 221 | /* 4.2.9.2 */ 222 | 223 | /* 224 | * The input of this method is the interpolated LARp[0..7] array. 225 | * The reflection coefficients, rp[i], are used in the analysis 226 | * filter and in the synthesis filter. 227 | */ 228 | public static void LARp_to_rp( 229 | short[] LARp) /* [0..7] IN/OUT */ { 230 | short temp; 231 | 232 | for (int i = 0; i < 8; i++) { 233 | if (LARp[i] < 0) { 234 | temp = (short) (LARp[i] == Gsm_Def.MIN_WORD ? 235 | Gsm_Def.MAX_WORD : -(LARp[i])); 236 | 237 | LARp[i] = (short) (-((temp < 11059) ? temp << 1 238 | : ((temp < 20070) ? temp + 11059 239 | : Add.GSM_ADD((short) (temp >> 2), 240 | (short) 26112)))); 241 | } else { 242 | temp = LARp[i]; 243 | LARp[i] = (short) ((temp < 11059) ? temp << 1 244 | : ((temp < 20070) ? temp + 11059 245 | : Add.GSM_ADD((short) (temp >> 2), 246 | (short) 26112))); 247 | } 248 | } 249 | } 250 | 251 | 252 | /* 253 | * This procedure computes the short term residual signal d[..] to be fed 254 | * to the RPE-LTP loop from the s[..] signal and from the local rp[..] 255 | * array (quantized reflection coefficients). As the call of this 256 | * procedure can be done in many ways (see the interpolation of the LAR 257 | * coefficient), it is assumed that the computation begins with index 258 | * k_start (for arrays d[..] and s[..]) and stops with index k_end 259 | * (k_start and k_end are defined in 4.2.9.1). This procedure also 260 | * needs to keep the array u[0..7] in memory for each call. 261 | */ 262 | private void Short_term_analysis_filtering( 263 | Gsm_State S, 264 | short[] rp, /* [0..7] IN */ 265 | int k_n, /* k_end - k_start */ 266 | short[] s, /* [0..n-1] IN/OUT */ 267 | int s_index) { 268 | short[] u = S.getU(); 269 | short di = 0, zzz = 0, ui = 0, sav = 0, rpi = 0; 270 | 271 | while (k_n != 0) { 272 | k_n--; 273 | 274 | di = sav = s[s_index]; 275 | 276 | for (int i = 0; i < 8; i++) { /* YYY */ 277 | ui = u[i]; 278 | rpi = rp[i]; 279 | u[i] = sav; 280 | 281 | zzz = Add.GSM_MULT_R(rpi, di); 282 | sav = Add.GSM_ADD(ui, zzz); 283 | 284 | zzz = Add.GSM_MULT_R(rpi, ui); 285 | di = Add.GSM_ADD(di, zzz); 286 | } 287 | s[s_index++] = di; 288 | } 289 | S.setU(u); 290 | } 291 | 292 | 293 | public static void Short_term_synthesis_filtering( 294 | Gsm_State S, 295 | short[] rrp, /* [0..7] IN */ 296 | int k, /* k_end - k_start */ 297 | short[] wt, /* [0..k-1] IN */ 298 | int[] sr, /* [0..k-1] OUT */ 299 | int wt_sr_index_start) { 300 | short[] v_temp = S.getV(); 301 | short sri = 0, tmp1 = 0, tmp2 = 0; 302 | int ltmp = 0; /* for GSM_ADD & GSM_SUB */ 303 | 304 | int index = wt_sr_index_start; 305 | 306 | while (k != 0) { 307 | k--; 308 | sri = wt[index]; 309 | for (int i = 7; i >= 0; i--) { 310 | 311 | /* sri = GSM_SUB( sri, gsm_mult_r( rrp[i], 312 | * v_temp[i] ) ); 313 | */ 314 | 315 | tmp1 = rrp[i]; 316 | tmp2 = v_temp[i]; 317 | tmp2 = (short) (tmp1 == Gsm_Def.MIN_WORD && 318 | tmp2 == Gsm_Def.MIN_WORD 319 | ? Gsm_Def.MAX_WORD 320 | : 0x0FFFF & (((int) tmp1 * (int) tmp2 321 | + 16384) >> 15)); 322 | 323 | sri = Add.GSM_SUB(sri, tmp2); 324 | 325 | /* v[i+1] = GSM_ADD( v_temp[i], 326 | * gsm_mult_r( rrp[i], sri ) ); 327 | */ 328 | 329 | tmp1 = (short) (tmp1 == Gsm_Def.MIN_WORD && 330 | sri == Gsm_Def.MIN_WORD 331 | ? Gsm_Def.MAX_WORD 332 | : 0x0FFFF & (((int) tmp1 * (int) sri 333 | + 16384) >> 15)); 334 | 335 | v_temp[i + 1] = Add.GSM_ADD(v_temp[i], tmp1); 336 | } 337 | sr[index++] = v_temp[0] = sri; 338 | } 339 | S.setV(v_temp); 340 | } 341 | } 342 | -------------------------------------------------------------------------------- /src/main/java/org/asteriskjava/iax/audio/javasound/ABuffer.java: -------------------------------------------------------------------------------- 1 | 2 | package org.asteriskjava.iax.audio.javasound; 3 | 4 | /** 5 | * class to encapsulate the concept of an audio buffer and it's state 6 | */ 7 | public class ABuffer { 8 | 9 | 10 | private byte[] _buff; 11 | private boolean _written; 12 | private long _stamp; 13 | private long _astamp; 14 | 15 | public ABuffer(int sz) { 16 | _buff = new byte[sz]; 17 | } 18 | 19 | public byte[] getBuff() { 20 | return _buff; 21 | } 22 | 23 | public boolean isWritten() { 24 | return _written; 25 | } 26 | 27 | public void setWritten() { 28 | _written = true; 29 | } 30 | 31 | public void setRead() { 32 | _written = false; 33 | } 34 | 35 | public long getStamp() { 36 | return _stamp; 37 | } 38 | 39 | public void setStamp(long stamp) { 40 | _stamp = stamp; 41 | } 42 | 43 | public long getAStamp() { 44 | return _astamp; 45 | } 46 | 47 | public void setAStamp(long as) { 48 | _astamp = as; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/org/asteriskjava/iax/audio/javasound/AbstractAudio.java: -------------------------------------------------------------------------------- 1 | 2 | package org.asteriskjava.iax.audio.javasound; 3 | 4 | import org.asteriskjava.iax.protocol.AudioSender; 5 | 6 | import java.io.IOException; 7 | 8 | /** 9 | * Base class for codecs that can convert to and from SLIN 10 | * It assumes that Audio8k will find and talk to SLIN hardware 11 | * It assumes that classes that extend it will implement the 12 | * abstract methods for their own codecs. 13 | */ 14 | public abstract class AbstractAudio 15 | implements AudioInterface { 16 | 17 | 18 | /** 19 | * Description of the Field 20 | */ 21 | protected Audio8k _a8; 22 | 23 | /** 24 | * Description of the Field 25 | */ 26 | protected byte[] _obuff; 27 | 28 | /** 29 | * Description of the Field 30 | */ 31 | protected byte[] _ibuff; 32 | 33 | /** 34 | * Description of the Method 35 | * 36 | * @return Description of the Returned Value 37 | */ 38 | @Override 39 | public long startRec() { 40 | return _a8.startRec(); 41 | } 42 | 43 | /** 44 | * Description of the Method 45 | */ 46 | @Override 47 | public void startPlay() { 48 | _a8.startPlay(); 49 | } 50 | 51 | /** 52 | * Description of the Method 53 | */ 54 | @Override 55 | public void stopRec() { 56 | _a8.stopRec(); 57 | } 58 | 59 | /** 60 | * Description of the Method 61 | * 62 | * @param in Description of Parameter 63 | * @param out Description of Parameter 64 | */ 65 | public abstract void convertFromLin(byte[] in, byte[] out); 66 | 67 | /** 68 | * Description of the Method 69 | * 70 | * @param in Description of Parameter 71 | * @param out Description of Parameter 72 | */ 73 | public abstract void convertToLin(byte[] in, byte[] out); 74 | 75 | /** 76 | * Description of the Method 77 | */ 78 | @Override 79 | public void stopPlay() { 80 | _a8.stopPlay(); 81 | } 82 | 83 | /** 84 | * Description of the Method 85 | * 86 | * @param buff Description of Parameter 87 | * @return Description of the Returned Value 88 | * @throws IOException Description of Exception 89 | */ 90 | @Override 91 | public long readWithTime(byte[] buff) throws IOException { 92 | long ret = _a8.readWithTime(_ibuff); 93 | convertFromLin(_ibuff, buff); 94 | return ret; 95 | } 96 | 97 | @Override 98 | public long readDirect(byte[] buff) throws IOException { 99 | long ret = _a8.readDirect(_ibuff); 100 | convertFromLin(_ibuff, buff); 101 | return ret; 102 | } 103 | 104 | /** 105 | * Description of the Method 106 | * 107 | * @param buff Description of Parameter 108 | * @param timestamp Description of Parameter 109 | * @throws IOException Description of Exception 110 | */ 111 | @Override 112 | public void write(byte[] buff, long timestamp) throws IOException { 113 | convertToLin(buff, _obuff); 114 | _a8.write(_obuff, timestamp); 115 | } 116 | 117 | /** 118 | * Description of the Method 119 | * 120 | * @param f Description of Parameter 121 | */ 122 | @Override 123 | public void writeDirect(byte[] f) { 124 | byte[] tf = new byte[2 * f.length]; 125 | convertToLin(f, tf); 126 | _a8.writeDirect(tf); 127 | } 128 | 129 | 130 | /** 131 | * startRinging 132 | */ 133 | @Override 134 | public void startRinging() { 135 | _a8.startRinging(); 136 | } 137 | 138 | /** 139 | * stopRinging 140 | */ 141 | @Override 142 | public void stopRinging() { 143 | _a8.stopRinging(); 144 | } 145 | 146 | /** 147 | * Gets the formatBit attribute of the AbstractAudio object 148 | * 149 | * @return The formatBit value 150 | */ 151 | @Override 152 | public abstract int getFormatBit(); 153 | 154 | /** 155 | * Sets the audioSender attribute of the AbstractAudio object 156 | * 157 | * @param as The new audioSender value 158 | */ 159 | @Override 160 | public void setAudioSender(AudioSender as) { 161 | _a8.setAudioSender(as); 162 | } 163 | 164 | /** 165 | * Play an audio Stream, 166 | * 167 | * @param in InputStream 168 | * @throws IOException 169 | */ 170 | @Override 171 | public void playAudioStream(java.io.InputStream in) throws IOException { 172 | _a8.playAudioStream(in); 173 | } 174 | 175 | /** 176 | * produce occasional sample values 177 | * 178 | * @param slis SampleListener 179 | * @throws IOException 180 | */ 181 | 182 | 183 | @Override 184 | public Integer supportedCodecs() { 185 | return _a8.supportedCodecs(); 186 | } 187 | 188 | @Override 189 | public String codecPrefString() { 190 | return _a8.codecPrefString(); 191 | } 192 | 193 | @Override 194 | public void cleanUp() { 195 | _a8.cleanUp(); 196 | } 197 | 198 | @Override 199 | public AudioInterface getByFormat(Integer format) { 200 | return _a8.getByFormat(format); 201 | } 202 | } 203 | -------------------------------------------------------------------------------- /src/main/java/org/asteriskjava/iax/audio/javasound/AudioAlaw.java: -------------------------------------------------------------------------------- 1 | 2 | package org.asteriskjava.iax.audio.javasound; 3 | 4 | import org.asteriskjava.iax.protocol.Log; 5 | import org.asteriskjava.iax.protocol.VoiceFrame; 6 | import org.asteriskjava.iax.util.ByteBuffer; 7 | 8 | import javax.sound.sampled.AudioFormat; 9 | 10 | 11 | /** 12 | * Description of the Class 13 | */ 14 | public class AudioAlaw extends AbstractAudio { 15 | 16 | 17 | AudioFormat _alawFormat; 18 | private int _ss; 19 | 20 | 21 | /** 22 | * Constructor for the AudioAlaw object 23 | */ 24 | public AudioAlaw(Audio8k a8) { 25 | _a8 = a8; 26 | _ss = _a8.getSampSz(); 27 | Log.debug("8k buffer size = " + _ss); 28 | _obuff = new byte[_ss]; 29 | _ibuff = new byte[_ss]; 30 | 31 | } 32 | 33 | //////////////////// ALAW //////////////////////////// 34 | 35 | /* 36 | This source code is a product of Sun Microsystems, Inc. and is provided 37 | for unrestricted use. Users may copy or modify this source code without 38 | charge. 39 | linear2alaw() - Convert a 16-bit linear PCM value to 8-bit A-law 40 | linear2alaw() accepts an 16-bit integer and encodes it as A-law data. 41 | Linear Input Code Compressed Code 42 | ------------------------ --------------- 43 | 0000000wxyza 000wxyz 44 | 0000001wxyza 001wxyz 45 | 000001wxyzab 010wxyz 46 | 00001wxyzabc 011wxyz 47 | 0001wxyzabcd 100wxyz 48 | 001wxyzabcde 101wxyz 49 | 01wxyzabcdef 110wxyz 50 | 1wxyzabcdefg 111wxyz 51 | For further information see John C. Bellamy's Digital Telephony, 1982, 52 | John Wiley & Sons, pps 98-111 and 472-476. 53 | */ 54 | /* Quantization field mask. */ 55 | private final static byte QUANT_MASK = 0xf; 56 | 57 | /* Left shift for segment number. */ 58 | private final static byte SEG_SHIFT = 4; 59 | private final static short[] seg_end = { 60 | 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF 61 | }; 62 | 63 | 64 | /** 65 | * Description of the Method 66 | * 67 | * @param pcm_val Description of Parameter 68 | * @return Description of the Returned Value 69 | */ 70 | public static byte linear2alaw(short pcm_val) { 71 | /* 2's complement (16-bit range) */ 72 | byte mask; 73 | byte seg = 8; 74 | byte aval; 75 | 76 | if (pcm_val >= 0) { 77 | mask = (byte) 0xD5; 78 | /* sign (7th) bit = 1 */ 79 | } else { 80 | mask = 0x55; 81 | /* sign bit = 0 */ 82 | pcm_val = (short) (-pcm_val - 8); 83 | } 84 | 85 | /* 86 | Convert the scaled magnitude to segment number. 87 | */ 88 | for (int i = 0; i < 8; i++) { 89 | if (pcm_val <= seg_end[i]) { 90 | seg = (byte) i; 91 | break; 92 | } 93 | } 94 | 95 | /* Combine the sign, segment, and quantization bits. */ 96 | if (seg >= 8) { 97 | /* out of range, return maximum value. */ 98 | return (byte) ((0x7F ^ mask) & 0xFF); 99 | } else { 100 | aval = (byte) (seg << SEG_SHIFT); 101 | if (seg < 2) { 102 | aval |= (pcm_val >> 4) & QUANT_MASK; 103 | } else { 104 | aval |= (pcm_val >> (seg + 3)) & QUANT_MASK; 105 | } 106 | return (byte) ((aval ^ mask) & 0xFF); 107 | } 108 | } 109 | 110 | 111 | private static short[] a2l = { 112 | -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736, 113 | -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784, 114 | -2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368, 115 | -3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392, 116 | -22016, -20992, -24064, -23040, -17920, -16896, -19968, -18944, 117 | -30208, -29184, -32256, -31232, -26112, -25088, -28160, -27136, 118 | -11008, -10496, -12032, -11520, -8960, -8448, -9984, -9472, 119 | -15104, -14592, -16128, -15616, -13056, -12544, -14080, -13568, 120 | -344, -328, -376, -360, -280, -264, -312, -296, 121 | -472, -456, -504, -488, -408, -392, -440, -424, 122 | -88, -72, -120, -104, -24, -8, -56, -40, 123 | -216, -200, -248, -232, -152, -136, -184, -168, 124 | -1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184, 125 | -1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696, 126 | -688, -656, -752, -720, -560, -528, -624, -592, 127 | -944, -912, -1008, -976, -816, -784, -880, -848, 128 | 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736, 129 | 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784, 130 | 2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368, 131 | 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392, 132 | 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944, 133 | 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136, 134 | 11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472, 135 | 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568, 136 | 344, 328, 376, 360, 280, 264, 312, 296, 137 | 472, 456, 504, 488, 408, 392, 440, 424, 138 | 88, 72, 120, 104, 24, 8, 56, 40, 139 | 216, 200, 248, 232, 152, 136, 184, 168, 140 | 1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184, 141 | 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696, 142 | 688, 656, 752, 720, 560, 528, 624, 592, 143 | 944, 912, 1008, 976, 816, 784, 880, 848 144 | }; 145 | 146 | 147 | /** 148 | * Description of the Method 149 | * 150 | * @param ulawbyte Description of Parameter 151 | * @return Description of the Returned Value 152 | */ 153 | public static short alaw2linear(byte ulawbyte) { 154 | return a2l[ulawbyte & 0xFF]; 155 | } 156 | 157 | 158 | /** 159 | * Gets the audioFormat attribute of the AudioAlaw object 160 | * 161 | * @return The audioFormat value 162 | */ 163 | protected AudioFormat getAudioFormat() { 164 | if (_alawFormat == null) { 165 | try { 166 | _alawFormat = new AudioFormat( 167 | AudioFormat.Encoding.ALAW, 168 | 8000.0F, // sampleRate 169 | 8, // sampleSizeInBits 170 | 1, // channels 171 | 1, // frameSize 172 | 8000.0F, // frameRate 173 | false);// bigEndian 174 | 175 | } catch (Exception x) { 176 | Log.warn(x.getMessage()); 177 | } 178 | } 179 | return _alawFormat; 180 | } 181 | 182 | 183 | /** 184 | * changedProps 185 | */ 186 | @Override 187 | public void changedProps() { 188 | } 189 | 190 | 191 | /** 192 | * getSampSz 193 | * 194 | * @return int 195 | */ 196 | @Override 197 | public int getSampSz() { 198 | return 160; 199 | } 200 | 201 | 202 | /** 203 | * Description of the Method 204 | * 205 | * @param in Description of Parameter 206 | * @param out Description of Parameter 207 | */ 208 | @Override 209 | public void convertToLin(byte[] in, byte[] out) { 210 | convert(in, out); 211 | } 212 | 213 | 214 | /** 215 | * Description of the Method 216 | * 217 | * @param in Description of Parameter 218 | * @param out Description of Parameter 219 | */ 220 | @Override 221 | public void convertFromLin(byte[] in, byte[] out) { 222 | ByteBuffer bb = ByteBuffer.wrap(in); 223 | for (int i = 0; i < in.length / 2; i++) { 224 | short s = bb.getShort(); 225 | out[i] = linear2alaw(s); 226 | } 227 | } 228 | 229 | 230 | /** 231 | * convert 232 | * 233 | * @param in byte[] 234 | * @param out byte[] 235 | */ 236 | public static void convert(byte[] in, byte[] out) { 237 | ByteBuffer bb = ByteBuffer.wrap(out); 238 | for (int i = 0; i < in.length; i++) { 239 | short s = alaw2linear(in[i]); 240 | bb.putShort(s); 241 | } 242 | } 243 | 244 | 245 | /** 246 | * getFormatBit 247 | * 248 | * @return int 249 | */ 250 | @Override 251 | public int getFormatBit() { 252 | return VoiceFrame.ALAW_BIT; 253 | } 254 | 255 | 256 | } 257 | 258 | -------------------------------------------------------------------------------- /src/main/java/org/asteriskjava/iax/audio/javasound/AudioGSM.java: -------------------------------------------------------------------------------- 1 | 2 | package org.asteriskjava.iax.audio.javasound; 3 | 4 | import org.asteriskjava.iax.audio.encodings.gsm.Encoder; 5 | import org.asteriskjava.iax.audio.encodings.gsm.GSMDecoder; 6 | import org.asteriskjava.iax.protocol.Log; 7 | import org.asteriskjava.iax.protocol.VoiceFrame; 8 | import org.asteriskjava.iax.util.ByteBuffer; 9 | 10 | 11 | /** 12 | * @author Sebastian 13 | */ 14 | public class AudioGSM extends AbstractAudio { 15 | 16 | private Encoder encoder; 17 | 18 | AudioGSM(Audio8k a8) { 19 | _a8 = a8; 20 | _obuff = new byte[320]; 21 | _ibuff = new byte[a8.getSampSz()]; 22 | encoder = new Encoder(); 23 | } 24 | 25 | @Override 26 | public void convertFromLin(byte[] in, byte[] out) { 27 | 28 | short[] sbuff = new short[160]; 29 | 30 | ByteBuffer bb = ByteBuffer.wrap(in); 31 | for (int i = 0; i < in.length / 2; i++) { 32 | short s = bb.getShort(); 33 | sbuff[i] = s; 34 | } 35 | 36 | encoder.encode(sbuff, out); 37 | 38 | } 39 | 40 | @Override 41 | public void convertToLin(byte[] in, byte[] out) { 42 | try { 43 | 44 | int[] is = GSMDecoder.decode(in); 45 | for (int i = 0; i < is.length; i++) { 46 | _obuff[i * 2] = (byte) ((is[i] >> 8)); 47 | _obuff[1 + i * 2] = (byte) (0xff & (is[i])); 48 | } 49 | 50 | } catch (Exception ex) { 51 | Log.warn(ex.getMessage()); 52 | } 53 | 54 | } 55 | 56 | @Override 57 | public int getFormatBit() { 58 | return VoiceFrame.GSM_BIT; 59 | } 60 | 61 | @Override 62 | public int getSampSz() { 63 | return 33; 64 | } 65 | 66 | @Override 67 | public void changedProps() { 68 | 69 | } 70 | 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/org/asteriskjava/iax/audio/javasound/AudioInterface.java: -------------------------------------------------------------------------------- 1 | 2 | package org.asteriskjava.iax.audio.javasound; 3 | 4 | import org.asteriskjava.iax.protocol.AudioSender; 5 | 6 | import java.io.IOException; 7 | 8 | public interface AudioInterface { 9 | /** 10 | * Return the minimum sample size for use in creating buffers etc. 11 | * 12 | * @return int 13 | */ 14 | public int getSampSz(); 15 | 16 | /** 17 | * Read from the Microphone, using the buffer provided, 18 | * but _only_ filling getSampSz() bytes. 19 | * returns the timestamp of the sample from the audio clock. 20 | * 21 | * @param buff byte[] 22 | * @return long 23 | */ 24 | public long readWithTime(byte[] buff) throws IOException; 25 | 26 | public long readDirect(byte[] buff) throws IOException; 27 | 28 | /** 29 | * stop the reccorder - but don't throw it away. 30 | */ 31 | public void stopRec(); 32 | 33 | /** 34 | * start the recorder 35 | * returning the time... 36 | */ 37 | 38 | public long startRec(); 39 | 40 | /** 41 | * The Audio properties have changed so attempt to 42 | * re connect to a new device 43 | */ 44 | public void changedProps(); 45 | 46 | /** 47 | * Start the player 48 | */ 49 | public void startPlay(); 50 | 51 | /** 52 | * Stop the player 53 | */ 54 | public void stopPlay(); 55 | 56 | /** 57 | * play the sample given (getSampSz() bytes) 58 | * assuming that it's timestamp is long 59 | * 60 | * @param buff byte[] 61 | * @param timestamp long 62 | */ 63 | 64 | public void write(byte[] buff, long timestamp) throws IOException; 65 | 66 | public void writeDirect(byte[] buff) throws IOException; 67 | 68 | /** 69 | * startRinging 70 | */ 71 | public void startRinging(); 72 | 73 | /** 74 | * stopRinging 75 | */ 76 | public void stopRinging(); 77 | 78 | public int getFormatBit(); 79 | 80 | public void setAudioSender(AudioSender as); 81 | 82 | public void playAudioStream(java.io.InputStream in) throws IOException; 83 | 84 | public Integer supportedCodecs(); 85 | 86 | public String codecPrefString(); 87 | 88 | public void cleanUp(); 89 | 90 | public AudioInterface getByFormat(Integer format); 91 | 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/org/asteriskjava/iax/audio/javasound/AudioProperties.java: -------------------------------------------------------------------------------- 1 | 2 | package org.asteriskjava.iax.audio.javasound; 3 | 4 | 5 | import org.asteriskjava.iax.protocol.Log; 6 | 7 | import javax.sound.sampled.AudioSystem; 8 | import javax.sound.sampled.DataLine; 9 | import javax.sound.sampled.Line; 10 | import javax.sound.sampled.Mixer; 11 | import javax.sound.sampled.Mixer.Info; 12 | import java.util.Properties; 13 | import java.util.Vector; 14 | 15 | /** 16 | * Description of the Class 17 | */ 18 | public class AudioProperties 19 | extends Properties { 20 | 21 | 22 | public final static String OUTPUTDEVICE = "outputDevice"; 23 | public final static String INPUTDEVICE = "inputDevice"; 24 | private final static String BIGBUFF = "bigbuff"; 25 | private final static String AUDIO_IN = "audioIn"; 26 | private final static String AUDIO_OUT = "audioOut"; 27 | private final static String MONITOR = "monitor"; 28 | private final static String AEC = "aec"; 29 | private final static String STEREOREC = "stereoRec"; 30 | 31 | private static Properties __audioProps; 32 | 33 | 34 | /** 35 | * Gets the outputDeviceName attribute of the AudioProperties 36 | * class 37 | * 38 | * @return The outputDeviceName value 39 | */ 40 | public static String getOutputDeviceName() { 41 | String ret = get(OUTPUTDEVICE); 42 | return ret; 43 | } 44 | 45 | /** 46 | * Gets the inputDeviceName attribute of the AudioProperties class 47 | * 48 | * @return The inputDeviceName value 49 | */ 50 | public static String getInputDeviceName() { 51 | String ret = get(INPUTDEVICE); 52 | return ret; 53 | } 54 | 55 | /** 56 | * Description of the Method 57 | * 58 | * @param name Description of Parameter 59 | * @param val Description of Parameter 60 | */ 61 | private static void set(String name, String val) { 62 | if (__audioProps == null) { 63 | __audioProps = new Properties(); 64 | } 65 | __audioProps.put(name, val); 66 | Log.debug("set " + name + " to " + val); 67 | } 68 | 69 | /** 70 | * Description of the Method 71 | * 72 | * @param name Description of Parameter 73 | * @return Description of the Returned Value 74 | */ 75 | private static String get(String name) { 76 | String ret = null; 77 | if (__audioProps != null) { 78 | ret = (String) __audioProps.get(name); 79 | } 80 | return ret; 81 | } 82 | 83 | /** 84 | * Sets the inputDeviceName attribute of the AudioProperties class 85 | * 86 | * @param val The new inputDeviceName value 87 | */ 88 | public static void setInputDeviceName(String val) { 89 | set(INPUTDEVICE, val); 90 | } 91 | 92 | /** 93 | * Sets the outputDeviceName attribute of the AudioProperties 94 | * class 95 | * 96 | * @param val The new outputDeviceName value 97 | */ 98 | public static void setOutputDeviceName(String val) { 99 | set(OUTPUTDEVICE, val); 100 | } 101 | 102 | /** 103 | * Gets the mixIn attribute of the AudioProperties class 104 | * 105 | * @return The mixIn value 106 | */ 107 | public static String[] getMixIn() { 108 | String ret[] = null; 109 | Vector vres = new Vector(); 110 | Log.debug("in getMixIn() "); 111 | String preferred = getInputDeviceName(); 112 | boolean foundPreferred = false; 113 | Info[] mixes = AudioSystem.getMixerInfo(); 114 | for (int i = 0; i < mixes.length; i++) { 115 | Mixer.Info mixi = mixes[i]; 116 | String mixup = mixi.getName().trim(); 117 | Log.debug("mixer input " + mixup); 118 | Mixer mx = AudioSystem.getMixer(mixi); 119 | Line.Info[] infos = mx.getTargetLineInfo(); 120 | if ((infos != null) && (infos.length > 0) && 121 | (infos[0] instanceof DataLine.Info)) { 122 | vres.add(mixup); 123 | if (mixup.equals(preferred)) { 124 | foundPreferred = true; 125 | } 126 | } 127 | } 128 | 129 | // if there is a preferred one, put it on top 130 | ret = new String[vres.size()]; 131 | if (foundPreferred == true) { 132 | ret[0] = preferred; 133 | Log.debug("adding input " + preferred + " (preferred)"); 134 | int j = 1; 135 | for (int i = 0; i < ret.length; i++) { 136 | String mixup = (String) vres.elementAt(i); 137 | if (mixup.equals(preferred) == false) { 138 | ret[j] = (String) vres.elementAt(i); 139 | Log.debug("adding input " + mixup); 140 | j++; 141 | } 142 | } 143 | } else { 144 | for (int i = 0; i < ret.length; i++) { 145 | String mixup = (String) vres.elementAt(i); 146 | ret[i] = mixup; 147 | Log.debug("adding input " + mixup); 148 | } 149 | } 150 | Log.debug("ret.length = " + ret.length); 151 | 152 | return ret; 153 | } 154 | 155 | /** 156 | * Gets the mixOut attribute of the AudioProperties class 157 | * 158 | * @return The mixOut value 159 | */ 160 | public static String[] getMixOut() { 161 | String ret[] = null; 162 | Vector vres = new Vector(); 163 | Log.debug("in getMixIn() "); 164 | String preferred = getOutputDeviceName(); 165 | boolean foundPreferred = false; 166 | Info[] mixes = AudioSystem.getMixerInfo(); 167 | for (int i = 0; i < mixes.length; i++) { 168 | Mixer.Info mixi = mixes[i]; 169 | String mixup = mixi.getName().trim(); 170 | Mixer mx = AudioSystem.getMixer(mixi); 171 | Line.Info[] infos = mx.getSourceLineInfo(); 172 | if ((infos != null) && (infos.length > 0) && 173 | (infos[0] instanceof DataLine.Info)) { 174 | vres.add(mixup); 175 | if (mixup.equals(preferred)) { 176 | foundPreferred = true; 177 | } 178 | } 179 | } 180 | 181 | // if there is a preferred one, put it on top 182 | ret = new String[vres.size()]; 183 | if (foundPreferred == true) { 184 | ret[0] = preferred; 185 | Log.debug("adding output " + preferred + " (preferred)"); 186 | int j = 1; 187 | for (int i = 0; i < ret.length; i++) { 188 | String mixup = (String) vres.elementAt(i); 189 | if (mixup.equals(preferred) == false) { 190 | ret[j] = (String) vres.elementAt(i); 191 | j++; 192 | Log.debug("adding output " + mixup); 193 | } 194 | } 195 | } else { 196 | for (int i = 0; i < ret.length; i++) { 197 | String mixup = (String) vres.elementAt(i); 198 | ret[i] = mixup; 199 | Log.debug("adding output " + mixup); 200 | } 201 | } 202 | Log.debug("ret.length = " + ret.length); 203 | 204 | return ret; 205 | } 206 | 207 | /** 208 | * getBigBuff 209 | * 210 | * @return Boolean 211 | */ 212 | public static boolean getBigBuff() { 213 | boolean ret = false; 214 | String bb = get(BIGBUFF); 215 | if (bb != null) { 216 | ret = ("TRUE".compareToIgnoreCase(bb) == 0); 217 | } else { 218 | // - we know that jdk1.4 likes bigger buffers 219 | String jdkversion = System.getProperty("java.version"); 220 | if (jdkversion != null) { 221 | if (jdkversion.startsWith("1.5") || jdkversion.startsWith("1.6")) { 222 | ret = false; 223 | } else { 224 | ret = true; 225 | Log.warn("Pre jdk1.5 in use - Using bigger buffers"); 226 | } 227 | } 228 | 229 | if (ret == false) { 230 | // - so does Linux 231 | String osname = System.getProperty("os.name"); 232 | if (osname != null) { 233 | osname = osname.toLowerCase(); 234 | if (osname.startsWith("linux")) { 235 | ret = true; 236 | Log.warn("Linux in use - Using bigger buffers"); 237 | } 238 | } 239 | } 240 | } 241 | return ret; 242 | } 243 | 244 | /** 245 | * Sets the bigBuff attribute of the AudioProperties class 246 | * 247 | * @param val The new bigBuff value 248 | */ 249 | public static void setBigBuff(boolean val) { 250 | set(BIGBUFF, "" + val); 251 | } 252 | 253 | 254 | /** 255 | * Returns if we have been able to open an incoming audio device, i.e. 256 | * a microphone. 257 | * 258 | * @return True if we have opened incoming audio device, false if 259 | * otherwise 260 | */ 261 | public static boolean isAudioInUsable() { 262 | boolean ret = false; 263 | String bb = get(AUDIO_IN); 264 | if (bb != null) { 265 | ret = "TRUE".equalsIgnoreCase(bb); 266 | } 267 | return ret; 268 | } 269 | 270 | /** 271 | * Returns if we have been able to open an outgoing audio device, i.e. 272 | * a headset or speakers. 273 | * 274 | * @return True if we have opened outgoing audio device, false if 275 | * otherwise 276 | */ 277 | public static boolean isAudioOutUsable() { 278 | boolean ret = false; 279 | String bb = get(AUDIO_OUT); 280 | if (bb != null) { 281 | ret = "TRUE".equalsIgnoreCase(bb); 282 | } 283 | return ret; 284 | } 285 | 286 | /** 287 | * Sets if we have been able to open an incoming audio device, i.e. 288 | * a microphone. 289 | * 290 | * @param b True if we have opened incoming audio device, false if 291 | * otherwise 292 | */ 293 | static void setAudioInUsable(boolean b) { 294 | set(AUDIO_IN, Boolean.toString(b)); 295 | } 296 | 297 | /** 298 | * Sets if we have been able to open an outgoing audio device, i.e. 299 | * a headset or speakers. 300 | * 301 | * @param b True if we have opened outgoing audio device, false if 302 | * otherwise 303 | */ 304 | static void setAudioOutUsable(boolean b) { 305 | set(AUDIO_OUT, Boolean.toString(b)); 306 | } 307 | 308 | /** 309 | * Sets local audio recording on or off. 310 | * 311 | * @param b boolean 312 | */ 313 | static void setMonitor(boolean b) { 314 | set(MONITOR, Boolean.toString(b)); 315 | } 316 | 317 | public static boolean isMonitor() { 318 | boolean ret = false; 319 | String bb = get(MONITOR); 320 | if (bb != null) { 321 | ret = ("TRUE".compareToIgnoreCase(bb) == 0); 322 | } 323 | return ret; 324 | } 325 | 326 | /** 327 | * Sets local acoustic echo canceller on or off. 328 | * 329 | * @param b boolean 330 | */ 331 | static void setAEC(boolean b) { 332 | set(AEC, Boolean.toString(b)); 333 | } 334 | 335 | public static boolean isAEC() { 336 | boolean ret = false; 337 | String bb = get(AEC); 338 | if (bb != null) { 339 | ret = ("TRUE".compareToIgnoreCase(bb) == 0); 340 | } 341 | return ret; 342 | } 343 | 344 | /** 345 | * Sets local recording in stereo mode on or off 346 | * 347 | * @param b boolean 348 | */ 349 | static void setStereoRec(boolean b) { 350 | set(STEREOREC, Boolean.toString(b)); 351 | } 352 | 353 | public static boolean isStereoRec() { 354 | boolean ret = false; 355 | String bb = get(STEREOREC); 356 | if (bb != null) { 357 | ret = ("TRUE".compareToIgnoreCase(bb) == 0); 358 | } 359 | return ret; 360 | } 361 | 362 | /** 363 | * Returns if the datalines should be closed when Corraleta quits. 364 | * Some platforms crash when this happens. 365 | * 366 | * @return True if the lines should be closed, false otherwise. 367 | */ 368 | public static boolean closeDataLine() { 369 | boolean ret = true; 370 | try { 371 | String osname = System.getProperty("os.name"); 372 | if (osname != null) { 373 | osname = osname.toLowerCase(); 374 | Log.debug("AudioProperties.closeDateLine(): osname=" + osname); 375 | if (osname.startsWith("mac")) { 376 | ret = false; 377 | } 378 | } 379 | } catch (Exception exc) { 380 | Log.warn("AudioProperties.closeDateLine(): " 381 | + exc.getClass().getName() + " " + exc.getMessage()); 382 | } 383 | return ret; 384 | } 385 | 386 | } 387 | -------------------------------------------------------------------------------- /src/main/java/org/asteriskjava/iax/audio/javasound/AudioUlaw.java: -------------------------------------------------------------------------------- 1 | 2 | package org.asteriskjava.iax.audio.javasound; 3 | 4 | 5 | import org.asteriskjava.iax.protocol.Log; 6 | import org.asteriskjava.iax.protocol.VoiceFrame; 7 | import org.asteriskjava.iax.util.ByteBuffer; 8 | 9 | import javax.sound.sampled.AudioFormat; 10 | 11 | public class AudioUlaw 12 | extends AbstractAudio { 13 | AudioFormat _ulawFormat; 14 | 15 | 16 | private int _ss; 17 | private static final boolean ZEROTRAP = true; 18 | private static final short BIAS = 0x84; 19 | private static final int CLIP = 32635; 20 | private static final int exp_lut1[] = { 21 | 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 22 | 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 23 | 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 24 | 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 25 | 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 26 | 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 27 | 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 28 | 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 29 | 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 30 | 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 31 | 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 32 | 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 33 | 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 34 | 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 35 | 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 36 | 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 37 | }; 38 | 39 | AudioUlaw(Audio8k a8) { 40 | _a8 = a8; 41 | _ss = _a8.getSampSz(); 42 | Log.debug("8k buffer size = " + _ss); 43 | _obuff = new byte[_ss]; 44 | _ibuff = new byte[_ss]; 45 | } 46 | 47 | /** 48 | * Converts a linear signed 16bit sample to a uLaw byte. 49 | * Ported to Java by fb. 50 | *
Originally by:
51 | * Craig Reese: IDA/Supercomputing Research Center
52 | * Joe Campbell: Department of Defense
53 | * 29 September 1989
54 | */ 55 | public static byte linear2ulaw(int sample) { 56 | int sign, exponent, mantissa, ulawbyte; 57 | 58 | if (sample > 32767) { 59 | sample = 32767; 60 | } else if (sample < -32768) { 61 | sample = -32768; 62 | /* Get the sample into sign-magnitude. */ 63 | } 64 | sign = (sample >> 8) & 0x80; /* set aside the sign */ 65 | if (sign != 0) { 66 | sample = -sample; /* get magnitude */ 67 | } 68 | if (sample > CLIP) { 69 | sample = CLIP; /* clip the magnitude */ 70 | 71 | /* Convert from 16 bit linear to ulaw. */ 72 | } 73 | sample = sample + BIAS; 74 | exponent = exp_lut1[(sample >> 7) & 0xFF]; 75 | mantissa = (sample >> (exponent + 3)) & 0x0F; 76 | ulawbyte = ~(sign | (exponent << 4) | mantissa); 77 | if (ZEROTRAP) { 78 | if (ulawbyte == 0) { 79 | ulawbyte = 0x02; /* optional CCITT trap */ 80 | } 81 | } 82 | return ((byte) ulawbyte); 83 | } 84 | 85 | /* u-law to linear conversion table */ 86 | private static short[] u2l = { 87 | -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956, 88 | -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764, 89 | -15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412, 90 | -11900, -11388, -10876, -10364, -9852, -9340, -8828, -8316, 91 | -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140, 92 | -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092, 93 | -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004, 94 | -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980, 95 | -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436, 96 | -1372, -1308, -1244, -1180, -1116, -1052, -988, -924, 97 | -876, -844, -812, -780, -748, -716, -684, -652, 98 | -620, -588, -556, -524, -492, -460, -428, -396, 99 | -372, -356, -340, -324, -308, -292, -276, -260, 100 | -244, -228, -212, -196, -180, -164, -148, -132, 101 | -120, -112, -104, -96, -88, -80, -72, -64, 102 | -56, -48, -40, -32, -24, -16, -8, 0, 103 | 32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956, 104 | 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764, 105 | 15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412, 106 | 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316, 107 | 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140, 108 | 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092, 109 | 3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004, 110 | 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980, 111 | 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436, 112 | 1372, 1308, 1244, 1180, 1116, 1052, 988, 924, 113 | 876, 844, 812, 780, 748, 716, 684, 652, 114 | 620, 588, 556, 524, 492, 460, 428, 396, 115 | 372, 356, 340, 324, 308, 292, 276, 260, 116 | 244, 228, 212, 196, 180, 164, 148, 132, 117 | 120, 112, 104, 96, 88, 80, 72, 64, 118 | 56, 48, 40, 32, 24, 16, 8, 0 119 | }; 120 | 121 | public static short ulaw2linear(byte ulawbyte) { 122 | return u2l[ulawbyte & 0xFF]; 123 | } 124 | 125 | protected AudioFormat getAudioFormat() { 126 | if (_ulawFormat == null) { 127 | try { 128 | _ulawFormat = new AudioFormat( 129 | AudioFormat.Encoding.ULAW, 130 | 8000.0F, // sampleRate 131 | 8, // sampleSizeInBits 132 | 1, // channels 133 | 1, // frameSize 134 | 8000.0F, // frameRate 135 | false); // bigEndian 136 | 137 | } catch (Exception x) { 138 | Log.warn(x.getMessage()); 139 | } 140 | 141 | } 142 | return _ulawFormat; 143 | } 144 | 145 | 146 | /** 147 | * changedProps 148 | */ 149 | @Override 150 | public void changedProps() { 151 | } 152 | 153 | /** 154 | * getSampSz 155 | * 156 | * @return int 157 | */ 158 | @Override 159 | public int getSampSz() { 160 | return 160; 161 | } 162 | 163 | @Override 164 | public void convertToLin(byte[] in, byte[] out) { 165 | convert(in, out); 166 | } 167 | 168 | @Override 169 | public void convertFromLin(byte[] in, byte[] out) { 170 | ByteBuffer bb = ByteBuffer.wrap(in); 171 | for (int i = 0; i < out.length; i++) { 172 | short s = bb.getShort(); 173 | out[i] = linear2ulaw(s); 174 | } 175 | } 176 | 177 | /** 178 | * convert 179 | * 180 | * @param in byte[] 181 | * @param out byte[] 182 | */ 183 | public static void convert(byte[] in, byte[] out) { 184 | ByteBuffer bb = ByteBuffer.wrap(out); 185 | for (int i = 0; i < in.length; i++) { 186 | short s = ulaw2linear(in[i]); 187 | bb.putShort(s); 188 | } 189 | } 190 | 191 | /** 192 | * getFormatBit 193 | * 194 | * @return int 195 | */ 196 | @Override 197 | public int getFormatBit() { 198 | return VoiceFrame.ULAW_BIT; 199 | } 200 | 201 | } 202 | -------------------------------------------------------------------------------- /src/main/java/org/asteriskjava/iax/protocol/AudioSender.java: -------------------------------------------------------------------------------- 1 | 2 | package org.asteriskjava.iax.protocol; 3 | 4 | 5 | import org.asteriskjava.iax.audio.javasound.AudioInterface; 6 | 7 | import java.io.IOException; 8 | 9 | /** 10 | * Takes captured audio and sends it to the remote IAX 11 | */ 12 | public class AudioSender { 13 | 14 | private Call _call; 15 | private int _formatBit; 16 | private boolean _done = false; 17 | private long _astart; 18 | private long _cstart; 19 | private long _nextdue; 20 | private int _stamp; 21 | private char _lastminisent; 22 | private boolean _first; 23 | private AudioInterface _aif; 24 | private byte[] _buff; 25 | 26 | /** 27 | * Constructor for the AudioSender object 28 | * 29 | * @param aif The audio interface 30 | * @param ca The call object 31 | */ 32 | AudioSender(AudioInterface aif, Call ca) { 33 | _call = ca; 34 | _aif = aif; 35 | _formatBit = aif.getFormatBit(); 36 | _buff = new byte[_aif.getSampSz()]; 37 | 38 | _cstart = this._call.getTimestamp(); 39 | _nextdue = _cstart; 40 | _lastminisent = 0; 41 | _first = true; 42 | 43 | } 44 | 45 | /** 46 | * sending audio, using VoiceFrame and MiniFrame frames. 47 | */ 48 | public void send() throws IOException { 49 | 50 | if (!_done) { 51 | 52 | long stamp = _aif.readWithTime(_buff); 53 | long now = stamp - _astart + _cstart; 54 | _stamp = (int) _nextdue; 55 | char mstamp = (char) (0xffff & _stamp); 56 | if (_first || (mstamp < _lastminisent)) { 57 | _first = false; 58 | VoiceFrame vf = new VoiceFrame(_call); 59 | vf._sCall = _call.getLno().charValue(); 60 | vf._dCall = _call.getRno().charValue(); 61 | vf.setTimestampVal(_stamp); 62 | vf._subclass = _formatBit; 63 | vf.sendMe(_buff); 64 | Log.debug("sent Full voice frame"); 65 | // send a full audio frame 66 | } else { 67 | // send a miniframe 68 | MiniFrame mf = new MiniFrame(_call); 69 | mf._sCall = _call.getLno().charValue(); 70 | mf.setTimestampVal(mstamp); // ? 71 | mf.sendMe(_buff); 72 | Log.verb("sent voice mini frame " + (int) (mstamp / 20)); 73 | } 74 | // eitherway note it down 75 | _lastminisent = mstamp; 76 | // now workout how long to wait... 77 | _nextdue += 20; 78 | 79 | } 80 | 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/org/asteriskjava/iax/protocol/Binder.java: -------------------------------------------------------------------------------- 1 | package org.asteriskjava.iax.protocol; 2 | 3 | import org.asteriskjava.iax.audio.javasound.AudioInterface; 4 | import org.asteriskjava.iax.util.ByteBuffer; 5 | 6 | public abstract class Binder { 7 | 8 | abstract public void send(String string, ByteBuffer bs); 9 | 10 | abstract public Friend removeFriend(String _iad); 11 | 12 | 13 | abstract public void stop(); 14 | 15 | abstract public void unregister(ProtocolEventListener gui) throws Exception; 16 | 17 | abstract public AudioInterface getAudioFace(); 18 | 19 | abstract public void register(String username, String password, 20 | ProtocolEventListener gui, boolean wantIncoming) 21 | throws Exception; 22 | 23 | 24 | protected final static char[] hex = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; 25 | 26 | 27 | /** 28 | * Turns a byte array into a hexidecimal string, using the specified 29 | * character as separator. 30 | * 31 | * @param dig The byte array 32 | * @param sep The separator 33 | * @return The hex string 34 | */ 35 | 36 | public static String enHex(byte[] dig, Character sep) { 37 | StringBuilder ret = new StringBuilder(32); 38 | for (int i = 0; i < dig.length; i++) { 39 | int v = (0x7f & dig[i]) + ((dig[i] < 0) ? 128 : 0); 40 | int h = v >> 4; 41 | int l = v & 0xf; 42 | ret.append(hex[h]).append(hex[l]); 43 | if (sep != null) { 44 | ret.append(sep); 45 | } 46 | 47 | } 48 | return ret.toString(); 49 | } 50 | 51 | /** 52 | * getGuiEventSender 53 | * 54 | * @param _gui ProtocolEventListener 55 | * @return ProtocolEventListener 56 | */ 57 | public abstract ProtocolEventListener getGuiEventSender( 58 | ProtocolEventListener _gui); 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/org/asteriskjava/iax/protocol/BinderSE.java: -------------------------------------------------------------------------------- 1 | 2 | package org.asteriskjava.iax.protocol; 3 | 4 | 5 | import org.asteriskjava.iax.audio.javasound.AudioInterface; 6 | import org.asteriskjava.iax.ui.GuiEventSender; 7 | import org.asteriskjava.iax.util.ByteBuffer; 8 | 9 | import java.io.IOException; 10 | import java.net.*; 11 | import java.util.Collection; 12 | import java.util.HashMap; 13 | 14 | /** 15 | * Main program - binds the udp port. 16 | * Each Friend object (representing an Asterisk host) is associated with 17 | * one (or the) Binder object. 18 | */ 19 | public class BinderSE extends Binder implements Runnable { 20 | 21 | 22 | /** 23 | * The default IAX2 port (4569) 24 | */ 25 | final static int IAX2SOC = 4569; 26 | 27 | /** 28 | * The default buffer size (4096) 29 | */ 30 | final static int BUFFSZ = 4096; 31 | 32 | private DatagramSocket _lsoc; 33 | private boolean _done = false; 34 | private HashMap _friends = new HashMap(5); 35 | // private Hashtable _friends = new Hashtable(5); 36 | private Thread _listener; 37 | private String _host; 38 | private AudioInterface _a8; 39 | 40 | 41 | /** 42 | * Constructor for the Binder object 43 | * 44 | * @param host The asterisk host which will be our PBX 45 | * @throws SocketException Thrown if the datagram (udp) socket 46 | * cannot be created 47 | */ 48 | @SuppressWarnings("empty-statement") 49 | public BinderSE(String host, AudioInterface a8) throws SocketException { 50 | try { 51 | String jversion = System.getProperty("java.version"); 52 | Log.debug("Java version = " + jversion); 53 | } catch (Throwable t) { 54 | ;// don't care much 55 | } 56 | _host = host; 57 | _lsoc = new DatagramSocket(IAX2SOC); 58 | // _lsoc = new DatagramSocket(); 59 | // _lsoc.setTrafficClass(0x10); 60 | _listener = new Thread(this, "Binder Listen"); 61 | _listener.setPriority(Thread.MAX_PRIORITY - 1); 62 | _listener.start(); 63 | _a8 = a8; 64 | } 65 | 66 | 67 | /** 68 | * Set up the infrastructure to make (and optionally receive) 69 | * calls. If we register for incoming calls gui.registered(Friend, 70 | * boolean) will be called when the asterisk registration 71 | * succeeds. 72 | * 73 | * @param username A username to use 74 | * @param password The password for the user 75 | * @param gui A listener which needs to be told about the registration result 76 | * @param wantIncoming Whether we are waiting for incoming calls 77 | * @throws UnknownHostException 78 | */ 79 | @Override 80 | public void register(String username, String password, ProtocolEventListener gui, boolean wantIncoming) throws Exception { 81 | 82 | InetAddress iad = InetAddress.getByName(_host); 83 | Log.debug("registering with " + _host); 84 | Friend f = findFriend(iad); 85 | if (f == null) { 86 | f = new Friend(this, _host, gui); 87 | _friends.put(iad, f); 88 | } 89 | 90 | if (wantIncoming) { 91 | f.register(username, password); 92 | } else { 93 | //We return true so that the gui knows that the Friend is setup 94 | //correctly. If there was a problem we'd have bailed before now! 95 | if (gui != null) { 96 | gui.registered(f, true); 97 | } 98 | } 99 | } 100 | 101 | 102 | /** 103 | * Unregisters from the asterisk pbx. This will only happen if we 104 | * are registered indeed. 105 | * 106 | * @param gui A listener which needs to be told about the unregistration result 107 | * @throws UnknownHostException 108 | */ 109 | @Override 110 | public void unregister(ProtocolEventListener gui) throws Exception { 111 | 112 | InetAddress iad = InetAddress.getByName(_host); 113 | 114 | Log.debug("unregistering with " + _host); 115 | Friend f = findFriend(iad); 116 | if (f != null && f.isRegistered() == true) { 117 | f.unregister(); 118 | } else { 119 | //We return false so that the gui knows that the Friend is 120 | //unregistered. If there was a problem we'd have bailed before now! 121 | if (gui != null) { 122 | gui.registered(f, false); 123 | } 124 | } 125 | } 126 | 127 | 128 | /** 129 | * Stop listening, if we were listening. 130 | */ 131 | @Override 132 | public void stop() { 133 | _done = true; 134 | if (_listener != null) { 135 | _lsoc.close(); 136 | Log.debug("Closed Socket"); 137 | try { 138 | _listener.join(); 139 | Log.debug("Joined binder thread"); 140 | } catch (InterruptedException ex) { 141 | Log.warn(ex.getMessage()); 142 | } 143 | _listener = null; 144 | } 145 | // Birgit: is this the best place for it?? 146 | _a8.cleanUp(); 147 | } 148 | 149 | 150 | /** 151 | * Keeps listening for incoming data. 152 | * It will pass the data to our friend. 153 | * 154 | * @see Friend#recv(byte[]) 155 | */ 156 | @Override 157 | public void run() { 158 | byte buff[] = new byte[BUFFSZ]; 159 | while (!_done) { 160 | DatagramPacket dgp = new DatagramPacket(buff, BUFFSZ); 161 | try { 162 | _lsoc.receive(dgp); 163 | InetAddress iad = dgp.getAddress(); 164 | int len = dgp.getLength(); 165 | byte data[] = new byte[len]; 166 | System.arraycopy(buff, 0, data, 0, len); 167 | //packetDump(data, len, iad, dgp.getPort(), true); 168 | Friend f = findFriend(iad); 169 | if (f != null) { 170 | f.recv(data); 171 | } else { 172 | //throw new IAX2ProtocolException("no friends ?"); 173 | } 174 | } catch (IOException ex) { 175 | if (!_done) { 176 | Log.warn(ex.getMessage()); 177 | } 178 | } 179 | } 180 | // cleanup 181 | Collection fall = _friends.values(); 182 | while (!fall.isEmpty()) { 183 | Friend f = (Friend) fall.iterator().next(); 184 | f.stop(); 185 | } 186 | } 187 | 188 | 189 | /** 190 | * Sends a frame (as bytes) to a specified address 191 | * 192 | * @param h The asterisk host address 193 | * @param b The frame (in bytes) 194 | * @see Friend#send(ByteBuffer) 195 | */ 196 | @Override 197 | public void send(String h, ByteBuffer b) { 198 | InetAddress a = null; 199 | try { 200 | a = InetAddress.getByName(h); 201 | DatagramPacket p = new DatagramPacket(b.array(), b.position(), a, BinderSE.IAX2SOC); 202 | // packetDump(b.array(), b.position(), a, this.IAX2SOC, false); 203 | this._lsoc.send(p); 204 | 205 | } catch (Exception ex1) { 206 | ex1.printStackTrace(); 207 | } 208 | } 209 | 210 | /** 211 | * Find the friend that belongs to the specified address. 212 | * 213 | * @param iad The asterisk host address 214 | * @return The found Friend 215 | */ 216 | private Friend findFriend(InetAddress iad) { 217 | Friend ret = null; 218 | ret = (Friend) _friends.get(iad); 219 | return ret; 220 | } 221 | 222 | 223 | /** 224 | * Removes a friend. This will be called by friend when it has been 225 | * succesfully unregistered. 226 | * 227 | * @param host The asterisk host address 228 | * @return The found Friend 229 | */ 230 | @Override 231 | public Friend removeFriend(String host) { 232 | InetAddress iad = null; 233 | Friend ret = null; 234 | try { 235 | iad = InetAddress.getByName(host); 236 | ret = (Friend) _friends.remove(iad); 237 | } catch (UnknownHostException ex) { 238 | Log.warn(ex.getMessage()); 239 | } 240 | return ret; 241 | } 242 | 243 | @Override 244 | public AudioInterface getAudioFace() { 245 | return _a8; 246 | } 247 | 248 | /** 249 | * Dumps information of a frame (in bytes) to standard error. 250 | * 251 | * @param bs The in- or outgoing frame (in bytes) 252 | * @param i The package size 253 | * @param a The asterisk host address 254 | * @param i1 The port number 255 | * @param in Is it in (true) or outgoing (false) 256 | */ 257 | protected void packetDump(byte[] bs, int i, InetAddress a, int i1, 258 | boolean in) { 259 | StringBuffer os = new StringBuffer(500); 260 | if (in) { 261 | os.append("Packet got from ").append(a.getHostAddress()).append(":"). 262 | append(i1).append('\n'); 263 | } else { 264 | os.append("Packet sent to ").append(a.getHostAddress()).append(":"). 265 | append(i1).append('\n'); 266 | } 267 | os.append("Packet size = ").append(i).append('\n'); 268 | byte[] bf = new byte[i]; 269 | System.arraycopy(bs, 0, bf, 0, i); 270 | os.append(enHex(bf, Character.valueOf(' '))); 271 | os.append('\n'); 272 | System.err.print(os); 273 | } 274 | 275 | /** 276 | * getGuiEventSender 277 | * 278 | * @param _gui ProtocolEventListener 279 | * @return ProtocolEventListener 280 | */ 281 | @Override 282 | public ProtocolEventListener getGuiEventSender(ProtocolEventListener _gui) { 283 | return new GuiEventSender(_gui); 284 | } 285 | 286 | } 287 | 288 | -------------------------------------------------------------------------------- /src/main/java/org/asteriskjava/iax/protocol/CallManager.java: -------------------------------------------------------------------------------- 1 | 2 | package org.asteriskjava.iax.protocol; 3 | 4 | public interface CallManager { 5 | /** 6 | * Returns if we can deal with this call or not. Pretends to be a 7 | * small PBX. Calls can be rejected if (for example) there isn't a 8 | * telephone plugged into this extension. 9 | */ 10 | public boolean accept(Call ca); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/org/asteriskjava/iax/protocol/ControlFrame.java: -------------------------------------------------------------------------------- 1 | 2 | package org.asteriskjava.iax.protocol; 3 | 4 | 5 | import org.asteriskjava.iax.util.ByteBuffer; 6 | 7 | /** 8 | * Represents an IAX ControlFrame. 9 | */ 10 | public class ControlFrame extends FullFrame { 11 | 12 | 13 | final static int HANGUP = 1; 14 | final static int OLD_RING = 2; 15 | final static int RINGING = 3;// (ringback) 16 | final static int ANSWER = 4; 17 | final static int BUSY = 5; 18 | final static int CONGESTION = 8; 19 | final static int FLASH = 9; 20 | final static int OLD_WINK = 10; 21 | final static int OPTION = 11; 22 | final static int KEYRADIO = 12; 23 | final static int UNKEYRADIO = 13; 24 | final static int CALLPROGRESS = 14; 25 | final static int CALLPROCEEDING = 15; 26 | final static int HOLD = 16; 27 | final static int UNHOLD = 17; 28 | 29 | 30 | static String[] controlTypes = { 31 | "ZERO", 32 | "Hangup", 33 | "Reserved", 34 | "Ringing", 35 | "Answer", 36 | "Busy", 37 | "Reserved", 38 | "Reserved", 39 | "Congestion", 40 | "Flash Hook", 41 | "Reserved", 42 | "Option", 43 | "Key Radio", 44 | "Unkey Radio", 45 | "Call Progress", 46 | "Call Proceeding", 47 | "Hold", 48 | "Unhold", 49 | "", 50 | "", 51 | "", 52 | "", 53 | "", 54 | "", 55 | "", 56 | "", 57 | "", 58 | "Quelchmoh", 59 | "", 60 | "Quelch", 61 | "Unquelch" 62 | }; 63 | 64 | 65 | /** 66 | * The outbound constructor. 67 | * 68 | * @param p0 The Call object 69 | */ 70 | public ControlFrame(Call p0) { 71 | super(p0); 72 | this._frametype = FullFrame.CONTROL; 73 | } 74 | 75 | 76 | /** 77 | * The inbound constructor. 78 | * 79 | * @param p0 The Call object 80 | * @param p1 The incoming message bytes 81 | */ 82 | public ControlFrame(Call p0, byte[] p1) { 83 | super(p0, p1); 84 | } 85 | 86 | 87 | /** 88 | * ack is called to send any required response. 89 | */ 90 | @Override 91 | void ack() { 92 | switch (this._subclass) { 93 | case RINGING: 94 | this.sendAck(); 95 | _call.setRinging(); 96 | break; 97 | case ANSWER: 98 | this.sendAck(); 99 | _call.setAnswered(true); 100 | break; 101 | default: 102 | Log.warn("Unhandled Control Frame " + _subclass); 103 | this.sendAck(); 104 | break; 105 | } 106 | log("got"); 107 | } 108 | 109 | 110 | /** 111 | * Sends an answer (ANSWER) back. 112 | */ 113 | public void sendAnswer() { 114 | _subclass = ControlFrame.ANSWER; 115 | Log.debug("Sending Answer"); 116 | sendMe(ControlFrame.EMPTY); 117 | } 118 | 119 | public void SendHold() { 120 | 121 | 122 | _subclass = ControlFrame.HOLD; 123 | _data = new ByteBuffer(); 124 | 125 | 126 | sendMe(ControlFrame.EMPTY); 127 | 128 | Log.debug("Sending Hold"); 129 | } 130 | 131 | public void SendUnHold() { 132 | 133 | _subclass = ControlFrame.UNHOLD; 134 | Log.debug("Sending UnHold"); 135 | sendMe(ControlFrame.EMPTY); 136 | } 137 | 138 | 139 | /** 140 | * Logs this frame. 141 | * 142 | * @param inout Additional text to log 143 | */ 144 | @Override 145 | protected void log(String inout) { 146 | StringBuilder bu = new StringBuilder(inout); 147 | bu.append(" Control Frame "); 148 | if ((_subclass < controlTypes.length) && (_subclass >= 0)) { 149 | bu.append(controlTypes[_subclass]); 150 | } else { 151 | bu.append(_subclass); 152 | } 153 | super.log(bu.toString()); 154 | } 155 | 156 | 157 | // Birgit: Why not remove this. It does less than its parent class. 158 | 159 | /** 160 | * arrived is called when a packet arrives. This method is 161 | * empty. 162 | * 163 | * @throws IAX2ProtocolException 164 | */ 165 | @Override 166 | void arrived() throws IAX2ProtocolException { 167 | } 168 | 169 | } 170 | 171 | -------------------------------------------------------------------------------- /src/main/java/org/asteriskjava/iax/protocol/DtmfFrame.java: -------------------------------------------------------------------------------- 1 | 2 | package org.asteriskjava.iax.protocol; 3 | 4 | /** 5 | * Represents an IAX DTMF FRAME 6 | */ 7 | class DtmfFrame extends FullFrame { 8 | 9 | /** 10 | * The outbound constructor. 11 | * 12 | * @param ca The Call object 13 | * @param c The outgoing DTMF character: 0-9, A-D, *, # 14 | */ 15 | DtmfFrame(Call ca, char c) { 16 | super(ca); 17 | _retry = false; 18 | _cbit = false; 19 | _frametype = FullFrame.DTMF; 20 | _subclass = 0x7f & c; 21 | byte buf[] = new byte[0]; 22 | sendMe(buf); 23 | Log.debug("Sent DTMF " + c); 24 | this.dump(); 25 | } 26 | 27 | 28 | /** 29 | * ack is called to send any required response. This method is empty 30 | * (for the moment?). 31 | */ 32 | @Override 33 | void ack() { 34 | // inbound - ignore it for now.... 35 | } 36 | 37 | } 38 | 39 | -------------------------------------------------------------------------------- /src/main/java/org/asteriskjava/iax/protocol/Frame.java: -------------------------------------------------------------------------------- 1 | 2 | package org.asteriskjava.iax.protocol; 3 | 4 | 5 | import org.asteriskjava.iax.util.ByteBuffer; 6 | 7 | /** 8 | * Base class for all frames 9 | */ 10 | abstract class Frame { 11 | 12 | 13 | final static byte[] EMPTY = new byte[0]; 14 | 15 | /** 16 | * The call object 17 | */ 18 | protected Call _call; 19 | 20 | /** 21 | * The timestamp 22 | */ 23 | protected Long _timestamp; 24 | 25 | /** 26 | * The F bit 27 | */ 28 | protected boolean _fullBit; 29 | 30 | /** 31 | * The source call number 32 | */ 33 | protected int _sCall; 34 | 35 | /** 36 | * The data 37 | */ 38 | protected ByteBuffer _data; 39 | 40 | 41 | /** 42 | * Sets the timestamp as int. 43 | * 44 | * @param v The timestamp 45 | * @see #setTimestamp(Long) 46 | */ 47 | void setTimestampVal(long v) { 48 | _timestamp = Long.valueOf(v); 49 | } 50 | 51 | 52 | /** 53 | * Sets the timestamp as Integer object. 54 | * 55 | * @param val The timestamp 56 | * @see #setTimestampVal(long) 57 | */ 58 | void setTimestamp(Long val) { 59 | _timestamp = val; 60 | } 61 | 62 | 63 | /** 64 | * Returns the timestamp as int 65 | * 66 | * @return the timestamp 67 | * @see #getTimestamp 68 | */ 69 | long getTimestampVal() { 70 | long ret = 0; 71 | if (_timestamp != null) { 72 | ret = _timestamp.longValue(); 73 | } 74 | return ret; 75 | } 76 | 77 | 78 | /** 79 | * Returns the timestamp as Integer object 80 | * 81 | * @return the timestamp 82 | * @see #getTimestampVal 83 | */ 84 | Long getTimestamp() { 85 | return _timestamp; 86 | } 87 | 88 | 89 | /** 90 | * arrived is called when a packet arrives. 91 | * 92 | * @throws IAX2ProtocolException 93 | */ 94 | abstract void arrived() throws IAX2ProtocolException; 95 | 96 | 97 | /** 98 | * ack is called to send any required response. 99 | */ 100 | abstract void ack(); 101 | } 102 | 103 | -------------------------------------------------------------------------------- /src/main/java/org/asteriskjava/iax/protocol/IAX2ProtocolException.java: -------------------------------------------------------------------------------- 1 | 2 | package org.asteriskjava.iax.protocol; 3 | 4 | import java.io.IOException; 5 | 6 | /** 7 | * Generic protocol exception for IAX2 Protocol 8 | */ 9 | public class IAX2ProtocolException extends IOException { 10 | 11 | 12 | public IAX2ProtocolException() { 13 | } 14 | 15 | public IAX2ProtocolException(String p0) { 16 | super(p0); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/asteriskjava/iax/protocol/Log.java: -------------------------------------------------------------------------------- 1 | 2 | package org.asteriskjava.iax.protocol; 3 | 4 | /** 5 | * Dumb substitute for a logger 6 | */ 7 | public class Log { 8 | 9 | /** 10 | * Log level ALL 11 | */ 12 | public static int ALL = 9; 13 | /** 14 | * Log level PROL(IX) 15 | */ 16 | public static int PROL = 6; 17 | /** 18 | * Log level VERB(OSE) 19 | */ 20 | public final static int VERB = 5; 21 | /** 22 | * Log level DEBUG 23 | */ 24 | public final static int DEBUG = 4; 25 | /** 26 | * Log level INFO(RMATION) 27 | */ 28 | public static int INFO = 3; 29 | /** 30 | * Log level WARN(ING) 31 | */ 32 | public final static int WARN = 2; 33 | /** 34 | * Log level ERROR (default) 35 | */ 36 | public static int ERROR = 1; 37 | /** 38 | * Log level NONE 39 | */ 40 | public static int NONE = 0; 41 | private static int _level = 1; 42 | 43 | 44 | /** 45 | * Constructor for the Log object 46 | */ 47 | public Log() { 48 | } 49 | 50 | 51 | /** 52 | * Sets the log level 53 | * 54 | * @param level The new level value 55 | */ 56 | public static void setLevel(int level) { 57 | _level = level; 58 | } 59 | 60 | 61 | /** 62 | * Returns the log level 63 | * 64 | * @return The level value 65 | */ 66 | public static int getLevel() { 67 | return _level; 68 | } 69 | 70 | /** 71 | * Logs Error message. 72 | * The message will only be logged if the log level is greater or 73 | * equal then the ERROR level. 74 | * 75 | * @param string The text to log 76 | */ 77 | public static void error(String string) { 78 | if (_level >= ERROR) { 79 | String message = "ERROR: " + System.currentTimeMillis() + " " + Thread.currentThread().getName() + "->" + string; 80 | System.out.println(message); 81 | } 82 | } 83 | 84 | /** 85 | * Logs a warning message. 86 | * The message will only be logged if the log level is greater or 87 | * equal then the WARN level. 88 | * 89 | * @param string The text to log 90 | */ 91 | public static void warn(String string) { 92 | if (_level >= WARN) { 93 | String message = "WARN: " + System.currentTimeMillis() + " " + Thread.currentThread().getName() + "->" + string; 94 | System.out.println(message); 95 | } 96 | } 97 | 98 | 99 | /** 100 | * Logs a debug message. 101 | * The message will only be logged if the log level is greater or 102 | * equal then the DEBUG level. 103 | * 104 | * @param string The text to log 105 | */ 106 | public static void debug(String string) { 107 | if (_level >= DEBUG) { 108 | String message = "DEBUG:" + System.currentTimeMillis() + " " + Thread.currentThread().getName() + "->" + string; 109 | System.out.println(message); 110 | } 111 | } 112 | 113 | 114 | /** 115 | * Logs a verbose message. 116 | * The message will only be logged if the log level is greater or 117 | * equal then the VERB level. 118 | * 119 | * @param string The text to log 120 | */ 121 | public static void verb(String string) { 122 | if (_level >= VERB) { 123 | String message = "VERB: " + System.currentTimeMillis() + " " + Thread.currentThread().getName() + "->" + string; 124 | System.out.println(message); 125 | } 126 | } 127 | 128 | /** 129 | * Logs a (very ?) verbose message. 130 | * The message will only be logged if the log level is greater or 131 | * equal then the PROL level. 132 | * 133 | * @param string The text to log 134 | */ 135 | public static void prol(String string) { 136 | if (_level >= VERB) { 137 | String message = "PROL: " + System.currentTimeMillis() + " " + Thread.currentThread().getName() + "->" + string; 138 | System.out.println(message); 139 | } 140 | } 141 | 142 | 143 | /** 144 | * Prints where this message was called from, via a stack trace. 145 | */ 146 | public static void where() { 147 | Exception x = new Exception("Called From"); 148 | x.printStackTrace(); 149 | } 150 | 151 | } 152 | 153 | -------------------------------------------------------------------------------- /src/main/java/org/asteriskjava/iax/protocol/MiniFrame.java: -------------------------------------------------------------------------------- 1 | 2 | package org.asteriskjava.iax.protocol; 3 | 4 | 5 | import org.asteriskjava.iax.util.ByteBuffer; 6 | 7 | import java.io.IOException; 8 | 9 | /** 10 | * Representation of a miniframe. 11 | *

12 | *

 13 |  *                      1                   2                   3
 14 |  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 15 |  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 16 |  * |F|     Source call number      |           time-stamp          |
 17 |  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 18 |  * |                                                               |
 19 |  * :                             Data                              :
 20 |  * |                                                               |
 21 |  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 22 |  * 
23 | */ 24 | public class MiniFrame extends Frame { 25 | 26 | 27 | private ByteBuffer _buff; 28 | 29 | 30 | /** 31 | * The outbound constructor. 32 | * 33 | * @param call The Call object 34 | */ 35 | public MiniFrame(Call call) { 36 | _call = call; 37 | _fullBit = false; 38 | } 39 | 40 | 41 | /** 42 | * The inbound constructor. 43 | * 44 | * @param call The Call object 45 | * @param bs The incoming message bytes 46 | * @throws IllegalArgumentException The bytes do not represent a 47 | * miniframe 48 | */ 49 | public MiniFrame(Call call, byte[] bs) 50 | throws IllegalArgumentException { 51 | ByteBuffer buf = ByteBuffer.wrap(bs); 52 | _sCall = buf.getShort(); 53 | if (_sCall < 0) { 54 | _sCall = 0x7fff & _sCall; 55 | _fullBit = true; 56 | throw new IllegalArgumentException("Not a miniframe, but fullframe."); 57 | } else { 58 | _fullBit = false; 59 | } 60 | setTimestampVal(buf.getChar()); 61 | _data = buf.slice(); 62 | _call = call; 63 | } 64 | 65 | 66 | /** 67 | * ack is called to send any required response. This method is 68 | * empty. 69 | */ 70 | @Override 71 | void ack() { 72 | } 73 | 74 | 75 | /** 76 | * Sends a specified buffer. The buffer represents the Data field in 77 | * the frame. If sets the header fields and calls sendMe() that will 78 | * do the actual sending. 79 | * 80 | * @param buff The buff (data) 81 | * @see #sendMe() 82 | */ 83 | public void sendMe(byte[] buff) { 84 | _buff = ByteBuffer.allocate(buff.length + 4); 85 | _buff.putChar((char) _sCall); 86 | _buff.putChar((char) (0xffff & getTimestampVal())); 87 | _buff.put(buff); 88 | sendMe(); 89 | } 90 | 91 | 92 | /** 93 | * used by data suppliers for outbound messages... put your data 94 | * on the end of this... 95 | * 96 | * @return ByteBuffer 97 | */ 98 | ByteBuffer getBuffer() { 99 | return _buff; 100 | } 101 | 102 | 103 | /** 104 | * arrived is called when a packet arrives. 105 | * 106 | * @throws IAX2ProtocolException 107 | */ 108 | @Override 109 | void arrived() throws IAX2ProtocolException { 110 | int fsz = _call.getFrameSz(); 111 | byte[] bs = new byte[fsz]; 112 | long ts = this.getTimestampVal(); 113 | int dr = _data.remaining(); 114 | if (dr < fsz) { 115 | Log.warn("buffer too short: " + dr + " not " + fsz); 116 | } else { 117 | _data.get(bs); 118 | try { 119 | _call.audioWrite(bs, ts); 120 | } catch (IOException ex) { 121 | Log.warn(ex.getMessage()); 122 | } 123 | } 124 | Log.verb("got minframe " + ts); 125 | } 126 | 127 | 128 | /** 129 | * Sends this frame. 130 | * 131 | * @see #sendMe(byte[]) 132 | * @see Call#send(ByteBuffer) 133 | */ 134 | void sendMe() { 135 | _call.send(_buff); 136 | } 137 | 138 | } 139 | 140 | -------------------------------------------------------------------------------- /src/main/java/org/asteriskjava/iax/protocol/ProtocolControlFrameNew.java: -------------------------------------------------------------------------------- 1 | 2 | package org.asteriskjava.iax.protocol; 3 | 4 | 5 | import org.asteriskjava.iax.audio.javasound.AudioInterface; 6 | 7 | /** 8 | * Special cases for outbound 'New' messages. 9 | */ 10 | class ProtocolControlFrameNew extends ProtocolControlFrame { 11 | 12 | 13 | /** 14 | * The outbound constructor. This sets the destination call number 15 | * to zero. 16 | * 17 | * @param p0 The Call object 18 | */ 19 | public ProtocolControlFrameNew(Call p0) { 20 | super(p0); 21 | _dCall = 0; 22 | _subclass = ProtocolControlFrameNew.NEW; 23 | this.setTimestampVal(0); 24 | _call.resetClock(); 25 | } 26 | 27 | 28 | /** 29 | * The inbound constructor. 30 | * 31 | * @param p0 The Call object 32 | * @param p1 The incoming message bytes 33 | */ 34 | public ProtocolControlFrameNew(Call p0, byte[] p1) { 35 | super(p0, p1); 36 | } 37 | 38 | 39 | /** 40 | * Returns if this is a NEW message. True by default. 41 | * 42 | * @return true if NEW, false otherwise 43 | */ 44 | @Override 45 | public boolean isANew() { 46 | return true; 47 | } 48 | 49 | 50 | /** 51 | * Sends this NEW message. 52 | * 53 | * @param cno The source call number 54 | * @param username The username (sent in IE) 55 | * @param calledNo The number we're calling (sent in IE) 56 | * @param callingNo Number/extension we call from (sent in IE) 57 | * @param callingName Name of the person calling (sent in IE) 58 | */ 59 | /* 60 | IE that can be sent: 61 | - 8.6.1. CALLED NUMBER 62 | - 8.6.2. CALLING NUMBER 63 | - 8.6.3. CALLING ANI 64 | - 8.6.4. CALLING NAME 65 | - 8.6.5. CALLED CONTEXT 66 | - 8.6.6. USERNAME 67 | - 8.6.8. CAPABILITY 68 | - 8.6.9. FORMAT 69 | - 8.6.10. LANGUAGE 70 | - 8.6.11. VERSION (MUST, and should be first) 71 | - 8.6.12. ADSICPE 72 | - 8.6.13. DNID 73 | - 8.6.25. AUTOANSWER 74 | - 8.6.31. DATETIME 75 | - 8.6.38. CALLINGPRES 76 | - 8.6.39. CALLINGTON 77 | - 8.6.43. ENCRYPTION 78 | - 8.6.45. CODEC PREFS 79 | */ 80 | public void sendNew(Character cno, String username, String calledNo, 81 | String callingNo, String callingName) { 82 | 83 | Log.debug("ProtocolControlFrameNew.sendNew: calledNo=" + calledNo 84 | + ", callingNo=" + callingNo 85 | + ", callingName=" + callingName 86 | + ", username=" + username); 87 | _sCall = cno.charValue(); 88 | _iseq = _call.getIseq(); 89 | _oseq = _call.getOseqInc(); 90 | 91 | InfoElement ie = new InfoElement(); 92 | ie.calledNo = calledNo; 93 | ie.callingNo = callingNo; 94 | ie.callingName = callingName; 95 | ie.username = username; 96 | AudioInterface a = _call.getAudioFace(); 97 | int format = a.supportedCodecs().intValue(); 98 | ie.format = VoiceFrame.GSM_BIT; 99 | ie.version = Integer.valueOf(2); 100 | ie.codec_prefs = a.codecPrefString().getBytes(); 101 | ie.capability = Integer.valueOf(format); 102 | // ie.putIaxVar("foobar","724024"); 103 | Log.debug("Sending initial NEW"); 104 | sendMe(ie); 105 | } 106 | 107 | 108 | /** 109 | * Commit this frame. This method is called when the NEW frame we sent 110 | * has been acked. This will call Call.gotAckToNew() 111 | * 112 | * @param ack The ack frame 113 | * @see Call#gotAckToNew(FullFrame) 114 | */ 115 | @Override 116 | void commit(FullFrame ack) { 117 | if (this._call != null) { 118 | _call.gotAckToNew(ack); 119 | } 120 | Log.debug("Commit on new called"); 121 | } 122 | 123 | } 124 | 125 | -------------------------------------------------------------------------------- /src/main/java/org/asteriskjava/iax/protocol/ProtocolEventListener.java: -------------------------------------------------------------------------------- 1 | 2 | package org.asteriskjava.iax.protocol; 3 | 4 | /** 5 | * Minimal events sent by the protocol engine. 6 | */ 7 | public interface ProtocolEventListener { 8 | public void newCall(Call c); 9 | 10 | public void registered(Friend f, boolean s); 11 | 12 | public void hungUp(Call c); 13 | 14 | public void ringing(Call c); 15 | 16 | public void answered(Call c); 17 | 18 | public void setHostReachable(Friend f, boolean b, int roundtrip); 19 | } 20 | 21 | -------------------------------------------------------------------------------- /src/main/java/org/asteriskjava/iax/protocol/Ringer.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * Benaiad@gmail.com 4 | */ 5 | package org.asteriskjava.iax.protocol; 6 | 7 | import javax.sound.sampled.*; 8 | import java.io.IOException; 9 | 10 | public class Ringer implements Runnable { 11 | 12 | String fileLocation = "ring.wav"; 13 | boolean stop = false; 14 | 15 | Ringer() { 16 | } 17 | 18 | public void start() { 19 | stop = false; 20 | Thread t = new Thread(this); 21 | t.start(); 22 | } 23 | 24 | public void run() { 25 | while (!stop) { 26 | playSound(fileLocation); 27 | try { 28 | Thread.sleep(1000); 29 | } catch (InterruptedException ex) { 30 | ; 31 | } 32 | } 33 | } 34 | 35 | public void stop() { 36 | stop = true; 37 | } 38 | 39 | private void playSound(String fileName) { 40 | //File soundFile = new File(fileName); 41 | AudioInputStream audioInputStream = null; 42 | try { 43 | audioInputStream = AudioSystem.getAudioInputStream(getClass().getResourceAsStream(fileName)); 44 | } catch (Exception e) { 45 | e.printStackTrace(); 46 | } 47 | AudioFormat audioFormat = audioInputStream.getFormat(); 48 | SourceDataLine line = null; 49 | DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat); 50 | try { 51 | line = (SourceDataLine) AudioSystem.getLine(info); 52 | line.open(audioFormat); 53 | } catch (LineUnavailableException e) { 54 | e.printStackTrace(); 55 | } catch (Exception e) { 56 | e.printStackTrace(); 57 | } 58 | line.start(); 59 | int nBytesRead = 0; 60 | byte[] abData = new byte[128000]; 61 | 62 | while (nBytesRead != -1 && !stop) { 63 | try { 64 | nBytesRead = audioInputStream.read(abData, 0, abData.length); 65 | } catch (IOException e) { 66 | e.printStackTrace(); 67 | } 68 | if (nBytesRead >= 0) { 69 | int nBytesWritten = line.write(abData, 0, nBytesRead); 70 | } 71 | } 72 | 73 | line.drain(); 74 | line.close(); 75 | } 76 | } -------------------------------------------------------------------------------- /src/main/java/org/asteriskjava/iax/protocol/VoiceFrame.java: -------------------------------------------------------------------------------- 1 | 2 | package org.asteriskjava.iax.protocol; 3 | 4 | import java.io.IOException; 5 | 6 | /** 7 | * VoiceFrame - The frame carries voice data. 8 | */ 9 | public class VoiceFrame extends FullFrame { 10 | 11 | 12 | /** 13 | * G.723.1 index 14 | */ 15 | public final static int G723_NO = 0; 16 | /** 17 | * Constant: G.723.1 - 4, 20, and 24 byte frames of 240 samples 18 | */ 19 | public final static int G723_BIT = 1 << G723_NO; 20 | 21 | /** 22 | * GSM Full Rate index 23 | */ 24 | public final static int GSM_NO = 1; 25 | /** 26 | * Constant: GSM Full Rate - 33 byte chunks of 160 samples or 65 byte chunks of 320 samples 27 | */ 28 | public final static int GSM_BIT = 1 << GSM_NO; 29 | 30 | /** 31 | * G.711 mu-law index 32 | */ 33 | public final static int ULAW_NO = 2; 34 | /** 35 | * Constant: G.711 mu-law - 1 byte per sample 36 | */ 37 | public final static int ULAW_BIT = 1 << ULAW_NO; 38 | 39 | /** 40 | * G.711 a-law index 41 | */ 42 | public final static int ALAW_NO = 3; 43 | /** 44 | * Constant: G.711 a-law - 1 byte per sample 45 | */ 46 | public final static int ALAW_BIT = 1 << ALAW_NO; 47 | 48 | /** 49 | * G.726 index 50 | */ 51 | public final static int G726_NO = 4; 52 | /** 53 | * Constant: G.726 54 | */ 55 | public final static int G726_BIT = 1 << G726_NO; 56 | 57 | /** 58 | * IMA ADPCM index 59 | */ 60 | public final static int ADPCM_NO = 5; 61 | /** 62 | * Constant: IMA ADPCM - 1 byte per 2 samples 63 | */ 64 | public final static int ADPCM_BIT = 1 << ADPCM_NO; 65 | 66 | /** 67 | * 16-bit linear little-endian index 68 | */ 69 | public final static int LIN16_NO = 6; 70 | /** 71 | * Constant: 16-bit linear little-endian - 2 bytes per sample 72 | */ 73 | public final static int LIN16_BIT = 1 << LIN16_NO; 74 | 75 | /** 76 | * LPC10 index 77 | */ 78 | public final static int LPC10_NO = 7; 79 | /** 80 | * Constant: LPC10 - Variable size frame of 172 samples 81 | */ 82 | public final static int LPC10_BIT = 1 << LPC10_NO; 83 | 84 | /** 85 | * G.729 index 86 | */ 87 | public final static int G729_NO = 8; 88 | /** 89 | * Constant: G.729 - 20 bytes chunks of 172 samples 90 | */ 91 | public final static int G729_BIT = 1 << G729_NO; 92 | 93 | /** 94 | * Speex index 95 | */ 96 | public final static int SPEEX_NO = 9; 97 | /** 98 | * Constant: Speex - Variable 99 | */ 100 | public final static int SPEEX_BIT = 1 << SPEEX_NO; 101 | 102 | /** 103 | * ILBC index 104 | */ 105 | public final static int ILBC_NO = 10; 106 | /** 107 | * Constant: ILBC - 50 bytes per 240 samples 108 | */ 109 | public final static int ILBC_BIT = 1 << ILBC_NO; 110 | 111 | /** 112 | * AMR narrowband index - not standardized. 113 | */ 114 | public final static int AMRN_NO = 14; 115 | 116 | public final static int AMRN_BIT = 1 << AMRN_NO; 117 | 118 | 119 | /** 120 | * JPEG index 121 | */ 122 | public final static int JPEG_NO = 16; 123 | /** 124 | * Constant: JPEG 125 | */ 126 | public final static int JPEG_BIT = 1 << JPEG_NO; 127 | 128 | /** 129 | * PNG index 130 | */ 131 | public final static int PNG_NO = 17; 132 | /** 133 | * Constant: PNG 134 | */ 135 | public final static int PNG_BIT = 1 << PNG_NO; 136 | 137 | /** 138 | * H261 index 139 | */ 140 | public final static int H261_NO = 18; 141 | /** 142 | * Constant: H261 143 | */ 144 | public final static int H261_BIT = 1 << H261_NO; 145 | 146 | /** 147 | * H263 index 148 | */ 149 | public final static int H263_NO = 19; 150 | /** 151 | * Constant: H263 152 | */ 153 | public final static int H263_BIT = 1 << H263_NO; 154 | 155 | /** 156 | * H263P index 157 | */ 158 | public final static int H263P_NO = 20; 159 | /** 160 | * Constant: H263P 161 | */ 162 | public final static int H263P_BIT = 1 << H263P_NO; 163 | 164 | 165 | /** 166 | * The outbound constructor. 167 | * 168 | * @param p0 The Call object 169 | */ 170 | public VoiceFrame(Call p0) { 171 | super(p0); 172 | _retry = false; 173 | _frametype = FullFrame.VOICE; 174 | } 175 | 176 | /** 177 | * The inbound constructor. 178 | * 179 | * @param p0 The Call object 180 | * @param p1 The incoming message bytes 181 | */ 182 | public VoiceFrame(Call p0, byte[] p1) { 183 | super(p0, p1); 184 | } 185 | 186 | 187 | /** 188 | * ack is called to send any required response. 189 | */ 190 | @Override 191 | void ack() { 192 | log("got"); 193 | switch (_subclass) { 194 | case GSM_BIT: 195 | case ULAW_BIT: 196 | case ALAW_BIT: 197 | case LIN16_BIT: 198 | case AMRN_BIT: 199 | sendAck(); 200 | break; 201 | default: 202 | Log.warn("Got unwanted Audio format " + _subclass); 203 | break; 204 | } 205 | } 206 | 207 | 208 | /** 209 | * Logs this frame. 210 | * 211 | * @param inout Additional text to log 212 | */ 213 | @Override 214 | protected void log(String inout) { 215 | super.log(inout + " voice frame"); 216 | } 217 | 218 | 219 | /** 220 | * arrived is called when a packet arrives. 221 | * 222 | * @throws IAX2ProtocolException 223 | */ 224 | @Override 225 | void arrived() throws IAX2ProtocolException { 226 | int fsz = _call.getFrameSz(); 227 | byte[] bs = new byte[fsz]; 228 | _data.get(bs); 229 | try { 230 | _call.fullVoiceFrameRcvd(this.getTimestampVal()); 231 | _call.audioWrite(bs, this.getTimestampVal() & 0xffff); 232 | } catch (IOException ex) { 233 | Log.warn(ex.getMessage()); 234 | } 235 | } 236 | 237 | } 238 | 239 | -------------------------------------------------------------------------------- /src/main/java/org/asteriskjava/iax/protocol/ring.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asterisk-java/asterisk-java-iax/27b63e2b307262eecba7fe98c62a42def799c2c2/src/main/java/org/asteriskjava/iax/protocol/ring.wav -------------------------------------------------------------------------------- /src/main/java/org/asteriskjava/iax/ui/BeanCanApplet.java: -------------------------------------------------------------------------------- 1 | 2 | package org.asteriskjava.iax.ui; 3 | 4 | import java.applet.Applet; 5 | 6 | 7 | public class BeanCanApplet extends Applet { 8 | 9 | 10 | String host = "192.168.99.254"; 11 | String user = "2001"; 12 | String pass = "1234"; 13 | 14 | 15 | Integer debug = 0; 16 | BeanCanFrameManager bcf; 17 | 18 | 19 | //Construct the applet 20 | public BeanCanApplet() { 21 | 22 | } 23 | 24 | //Initialize the applet 25 | @Override 26 | public void init() { 27 | 28 | try { 29 | jbInit(); 30 | } catch (Exception e) { 31 | e.printStackTrace(); 32 | } 33 | } 34 | 35 | //Component initialization 36 | private void jbInit() throws Exception { 37 | bcf = new BeanCanFrameManager(true, debug.intValue(), host); 38 | bcf.validate(); 39 | 40 | 41 | } 42 | 43 | //Start the applet 44 | @Override 45 | public void start() { 46 | 47 | if (bcf != null) { 48 | bcf.set_host(host); 49 | bcf.set_username(user); 50 | bcf.set_password(pass); 51 | bcf.set_debug(debug.intValue()); 52 | bcf.start(); 53 | bcf.register(); 54 | 55 | 56 | } 57 | } 58 | 59 | 60 | //Stop the applet 61 | @Override 62 | public void stop() { 63 | if (bcf != null) { 64 | bcf.stop(); 65 | } 66 | } 67 | 68 | //Destroy the applet 69 | @Override 70 | public void destroy() { 71 | 72 | if (bcf != null) { 73 | bcf.stop(); 74 | } 75 | 76 | } 77 | 78 | //Get Applet information 79 | @Override 80 | public String getAppletInfo() { 81 | return "Integra CCS"; 82 | } 83 | 84 | 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/org/asteriskjava/iax/ui/BeanCanFrame.java: -------------------------------------------------------------------------------- 1 | 2 | package org.asteriskjava.iax.ui; 3 | 4 | 5 | import org.asteriskjava.iax.util.DTMFGenerator; 6 | 7 | import javax.swing.*; 8 | import java.awt.*; 9 | import java.awt.event.ActionEvent; 10 | import java.awt.event.WindowEvent; 11 | 12 | 13 | public class BeanCanFrame extends JFrame { 14 | 15 | JPanel contentPane; 16 | JMenuBar jMenuBar1 = new JMenuBar(); 17 | JMenu jMenuFile = new JMenu(); 18 | JMenuItem jMenuFileExit = new JMenuItem(); 19 | JMenu jMenuHelp = new JMenu(); 20 | JMenuItem jMenuHelpAbout = new JMenuItem(); 21 | BorderLayout borderLayout1 = new BorderLayout(); 22 | JPanel jPanel1 = new JPanel(); 23 | JPanel jPanel2 = new JPanel(); 24 | JPanel jPanel3 = new JPanel(); 25 | JPanel jPanel4 = new JPanel(); 26 | BorderLayout borderLayout2 = new BorderLayout(); 27 | JTextField dialString = new JTextField(); 28 | GridLayout gridLayout1 = new GridLayout(); 29 | JButton jButton1 = new JButton(); 30 | JButton jButton2 = new JButton(); 31 | JButton jButton3 = new JButton(); 32 | JButton jButton4 = new JButton(); 33 | JButton jButton5 = new JButton(); 34 | JButton jButton6 = new JButton(); 35 | JButton jButton7 = new JButton(); 36 | JButton jButton8 = new JButton(); 37 | JButton jButton9 = new JButton(); 38 | JButton jButton0 = new JButton(); 39 | JButton jButton11 = new JButton(); 40 | JButton jButton12 = new JButton(); 41 | BorderLayout borderLayout3 = new BorderLayout(); 42 | JLabel status = new JLabel(); 43 | JButton act = new JButton(); 44 | JButton clear = new JButton(); 45 | JPanel jPanel5 = new JPanel(); 46 | GridLayout gridLayout2 = new GridLayout(); 47 | JPanel jPanel6 = new JPanel(); 48 | JPanel jPanel7 = new JPanel(); 49 | BorderLayout borderLayout4 = new BorderLayout(); 50 | BorderLayout borderLayout5 = new BorderLayout(); 51 | BorderLayout borderLayout6 = new BorderLayout(); 52 | 53 | //Construct the frame 54 | public BeanCanFrame() { 55 | enableEvents(AWTEvent.WINDOW_EVENT_MASK); 56 | try { 57 | jbInit(); 58 | } catch (Exception e) { 59 | e.printStackTrace(); 60 | } 61 | } 62 | 63 | //Component initialization 64 | private void jbInit() throws Exception { 65 | contentPane = (JPanel) this.getContentPane(); 66 | contentPane.setLayout(borderLayout1); 67 | this.setSize(new Dimension(300, 200)); 68 | this.setTitle("Integra CCS IaxJphone"); 69 | this.setAlwaysOnTop(true); 70 | 71 | jPanel1.setLayout(borderLayout2); 72 | dialString.setText(""); 73 | dialString.addActionListener(new BeanCanFrame_dialString_actionAdapter(this)); 74 | jPanel3.setLayout(gridLayout1); 75 | gridLayout1.setColumns(3); 76 | gridLayout1.setRows(4); 77 | jButton1.setMnemonic('1'); 78 | jButton1.setText("1"); 79 | jButton1.addActionListener(new BeanCanFrame_jButton1_actionAdapter(this)); 80 | jButton2.setMnemonic('2'); 81 | jButton2.setText("2"); 82 | jButton2.addActionListener(new BeanCanFrame_jButton2_actionAdapter(this)); 83 | jButton3.setMnemonic('3'); 84 | jButton3.setText("3"); 85 | jButton3.addActionListener(new BeanCanFrame_jButton3_actionAdapter(this)); 86 | jButton4.setText("4"); 87 | jButton4.addActionListener(new BeanCanFrame_jButton4_actionAdapter(this)); 88 | jButton5.setText("5"); 89 | jButton5.addActionListener(new BeanCanFrame_jButton5_actionAdapter(this)); 90 | jButton6.setText("6"); 91 | jButton6.addActionListener(new BeanCanFrame_jButton6_actionAdapter(this)); 92 | jButton7.setText("7"); 93 | jButton7.addActionListener(new BeanCanFrame_jButton7_actionAdapter(this)); 94 | jButton8.setText("8"); 95 | jButton8.addActionListener(new BeanCanFrame_jButton8_actionAdapter(this)); 96 | jButton9.setText("9"); 97 | jButton9.addActionListener(new BeanCanFrame_jButton9_actionAdapter(this)); 98 | jButton0.setText("0"); 99 | jButton0.addActionListener(new BeanCanFrame_jButton0_actionAdapter(this)); 100 | jButton11.setText("*"); 101 | jButton11.addActionListener(new BeanCanFrame_jButton11_actionAdapter(this)); 102 | jButton12.setAction(null); 103 | jButton12.setText("#"); 104 | jButton12.addActionListener(new BeanCanFrame_jButton12_actionAdapter(this)); 105 | jPanel2.setLayout(borderLayout3); 106 | status.setText("No Conectado"); 107 | jPanel4.setOpaque(true); 108 | jPanel4.setLayout(borderLayout6); 109 | act.setText("Llamar"); 110 | act.addActionListener(new BeanCanFrame_act_actionAdapter(this)); 111 | contentPane.setActionMap(null); 112 | clear.setText("Borrar"); 113 | clear.addActionListener(new BeanCanFrame_clear_actionAdapter(this)); 114 | jPanel5.setLayout(gridLayout2); 115 | gridLayout2.setColumns(2); 116 | jPanel7.setLayout(borderLayout4); 117 | jPanel6.setLayout(borderLayout5); 118 | jMenuFile.add(jMenuFileExit); 119 | jMenuHelp.add(jMenuHelpAbout); 120 | jMenuBar1.add(jMenuFile); 121 | jMenuBar1.add(jMenuHelp); 122 | contentPane.add(jPanel1, BorderLayout.CENTER); 123 | jPanel1.add(jPanel2, BorderLayout.NORTH); 124 | jPanel2.add(dialString, BorderLayout.CENTER); 125 | jPanel1.add(jPanel3, BorderLayout.CENTER); 126 | jPanel3.add(jButton1, null); 127 | jPanel3.add(jButton2, null); 128 | jPanel3.add(jButton3, null); 129 | jPanel3.add(jButton4, null); 130 | jPanel3.add(jButton5, null); 131 | jPanel3.add(jButton6, null); 132 | jPanel3.add(jButton7, null); 133 | jPanel3.add(jButton8, null); 134 | jPanel3.add(jButton9, null); 135 | jPanel3.add(jButton11, null); 136 | jPanel3.add(jButton0, null); 137 | jPanel3.add(jButton12, null); 138 | contentPane.add(jPanel4, BorderLayout.SOUTH); 139 | jPanel4.add(status, BorderLayout.CENTER); 140 | contentPane.add(jPanel5, BorderLayout.EAST); 141 | jPanel5.add(jPanel7, null); 142 | jPanel5.add(jPanel6, null); 143 | jPanel2.add(act, BorderLayout.EAST); 144 | jPanel2.add(clear, BorderLayout.WEST); 145 | this.setJMenuBar(jMenuBar1); 146 | 147 | } 148 | 149 | 150 | void hold() { 151 | 152 | } 153 | 154 | void button_action(ActionEvent e) { 155 | String t = e.getActionCommand(); 156 | String s = this.dialString.getText(); 157 | s = s + t; 158 | dialString.setText(s); 159 | } 160 | 161 | void dialString_actionPerformed(ActionEvent e) { 162 | String num = dialString.getText(); 163 | status.setText("Marcando: " + num); 164 | } 165 | 166 | void clear_actionPerformed(ActionEvent e) { 167 | dialString.setText(""); 168 | } 169 | 170 | void act_actionPerformed(ActionEvent e) { 171 | dialString_actionPerformed(e); 172 | } 173 | 174 | 175 | //Overridden so we can exit when window is closed 176 | @Override 177 | protected void processWindowEvent(WindowEvent e) { 178 | super.processWindowEvent(e); 179 | if (e.getID() == WindowEvent.WINDOW_CLOSING) { 180 | System.exit(0); 181 | } 182 | } 183 | 184 | /** 185 | * Acciones de Botones 186 | * 187 | * @author Sebastian 188 | */ 189 | 190 | class BeanCanFrame_jButton1_actionAdapter implements java.awt.event.ActionListener { 191 | BeanCanFrame adaptee; 192 | 193 | BeanCanFrame_jButton1_actionAdapter(BeanCanFrame adaptee) { 194 | this.adaptee = adaptee; 195 | } 196 | 197 | @Override 198 | public void actionPerformed(ActionEvent e) { 199 | DTMFGenerator.playTone("1"); 200 | 201 | adaptee.button_action(e); 202 | } 203 | } 204 | 205 | class BeanCanFrame_jButton2_actionAdapter implements java.awt.event.ActionListener { 206 | BeanCanFrame adaptee; 207 | 208 | BeanCanFrame_jButton2_actionAdapter(BeanCanFrame adaptee) { 209 | this.adaptee = adaptee; 210 | } 211 | 212 | @Override 213 | public void actionPerformed(ActionEvent e) { 214 | DTMFGenerator.playTone("2"); 215 | adaptee.button_action(e); 216 | } 217 | } 218 | 219 | class BeanCanFrame_jButton3_actionAdapter implements java.awt.event.ActionListener { 220 | BeanCanFrame adaptee; 221 | 222 | BeanCanFrame_jButton3_actionAdapter(BeanCanFrame adaptee) { 223 | this.adaptee = adaptee; 224 | } 225 | 226 | @Override 227 | public void actionPerformed(ActionEvent e) { 228 | DTMFGenerator.playTone("3"); 229 | adaptee.button_action(e); 230 | } 231 | } 232 | 233 | class BeanCanFrame_jButton4_actionAdapter implements java.awt.event.ActionListener { 234 | BeanCanFrame adaptee; 235 | 236 | BeanCanFrame_jButton4_actionAdapter(BeanCanFrame adaptee) { 237 | this.adaptee = adaptee; 238 | } 239 | 240 | @Override 241 | public void actionPerformed(ActionEvent e) { 242 | DTMFGenerator.playTone("4"); 243 | adaptee.button_action(e); 244 | } 245 | } 246 | 247 | class BeanCanFrame_jButton5_actionAdapter implements java.awt.event.ActionListener { 248 | BeanCanFrame adaptee; 249 | 250 | BeanCanFrame_jButton5_actionAdapter(BeanCanFrame adaptee) { 251 | this.adaptee = adaptee; 252 | } 253 | 254 | @Override 255 | public void actionPerformed(ActionEvent e) { 256 | DTMFGenerator.playTone("5"); 257 | adaptee.button_action(e); 258 | } 259 | } 260 | 261 | class BeanCanFrame_jButton6_actionAdapter implements java.awt.event.ActionListener { 262 | BeanCanFrame adaptee; 263 | 264 | BeanCanFrame_jButton6_actionAdapter(BeanCanFrame adaptee) { 265 | this.adaptee = adaptee; 266 | } 267 | 268 | @Override 269 | public void actionPerformed(ActionEvent e) { 270 | DTMFGenerator.playTone("6"); 271 | adaptee.button_action(e); 272 | } 273 | } 274 | 275 | class BeanCanFrame_jButton7_actionAdapter implements java.awt.event.ActionListener { 276 | BeanCanFrame adaptee; 277 | 278 | BeanCanFrame_jButton7_actionAdapter(BeanCanFrame adaptee) { 279 | this.adaptee = adaptee; 280 | } 281 | 282 | @Override 283 | public void actionPerformed(ActionEvent e) { 284 | DTMFGenerator.playTone("7"); 285 | adaptee.button_action(e); 286 | } 287 | } 288 | 289 | class BeanCanFrame_jButton8_actionAdapter implements java.awt.event.ActionListener { 290 | BeanCanFrame adaptee; 291 | 292 | BeanCanFrame_jButton8_actionAdapter(BeanCanFrame adaptee) { 293 | this.adaptee = adaptee; 294 | } 295 | 296 | @Override 297 | public void actionPerformed(ActionEvent e) { 298 | DTMFGenerator.playTone("8"); 299 | adaptee.button_action(e); 300 | } 301 | } 302 | 303 | class BeanCanFrame_jButton9_actionAdapter implements java.awt.event.ActionListener { 304 | BeanCanFrame adaptee; 305 | 306 | BeanCanFrame_jButton9_actionAdapter(BeanCanFrame adaptee) { 307 | this.adaptee = adaptee; 308 | } 309 | 310 | @Override 311 | public void actionPerformed(ActionEvent e) { 312 | DTMFGenerator.playTone("9"); 313 | adaptee.button_action(e); 314 | } 315 | } 316 | 317 | class BeanCanFrame_jButton11_actionAdapter implements java.awt.event.ActionListener { 318 | BeanCanFrame adaptee; 319 | 320 | BeanCanFrame_jButton11_actionAdapter(BeanCanFrame adaptee) { 321 | this.adaptee = adaptee; 322 | } 323 | 324 | @Override 325 | public void actionPerformed(ActionEvent e) { 326 | DTMFGenerator.playTone("*"); 327 | adaptee.button_action(e); 328 | 329 | } 330 | } 331 | 332 | class BeanCanFrame_jButton0_actionAdapter implements java.awt.event.ActionListener { 333 | BeanCanFrame adaptee; 334 | 335 | BeanCanFrame_jButton0_actionAdapter(BeanCanFrame adaptee) { 336 | this.adaptee = adaptee; 337 | } 338 | 339 | @Override 340 | public void actionPerformed(ActionEvent e) { 341 | DTMFGenerator.playTone("0"); 342 | adaptee.button_action(e); 343 | } 344 | } 345 | 346 | class BeanCanFrame_jButton12_actionAdapter implements java.awt.event.ActionListener { 347 | BeanCanFrame adaptee; 348 | 349 | BeanCanFrame_jButton12_actionAdapter(BeanCanFrame adaptee) { 350 | this.adaptee = adaptee; 351 | } 352 | 353 | @Override 354 | public void actionPerformed(ActionEvent e) { 355 | DTMFGenerator.playTone("#"); 356 | adaptee.button_action(e); 357 | } 358 | } 359 | 360 | 361 | class BeanCanFrame_dialString_actionAdapter implements java.awt.event.ActionListener { 362 | BeanCanFrame adaptee; 363 | 364 | BeanCanFrame_dialString_actionAdapter(BeanCanFrame adaptee) { 365 | this.adaptee = adaptee; 366 | } 367 | 368 | @Override 369 | public void actionPerformed(ActionEvent e) { 370 | adaptee.dialString_actionPerformed(e); 371 | } 372 | } 373 | 374 | class BeanCanFrame_clear_actionAdapter implements java.awt.event.ActionListener { 375 | BeanCanFrame adaptee; 376 | 377 | BeanCanFrame_clear_actionAdapter(BeanCanFrame adaptee) { 378 | this.adaptee = adaptee; 379 | } 380 | 381 | @Override 382 | public void actionPerformed(ActionEvent e) { 383 | adaptee.clear_actionPerformed(e); 384 | } 385 | } 386 | 387 | class BeanCanFrame_act_actionAdapter implements java.awt.event.ActionListener { 388 | BeanCanFrame adaptee; 389 | 390 | BeanCanFrame_act_actionAdapter(BeanCanFrame adaptee) { 391 | this.adaptee = adaptee; 392 | } 393 | 394 | @Override 395 | public void actionPerformed(ActionEvent e) { 396 | adaptee.act_actionPerformed(e); 397 | } 398 | } 399 | 400 | 401 | } -------------------------------------------------------------------------------- /src/main/java/org/asteriskjava/iax/ui/BeanCanFrameManager.java: -------------------------------------------------------------------------------- 1 | 2 | package org.asteriskjava.iax.ui; 3 | 4 | import org.asteriskjava.iax.audio.javasound.Audio8k; 5 | import org.asteriskjava.iax.audio.javasound.AudioInterface; 6 | import org.asteriskjava.iax.protocol.*; 7 | 8 | import java.awt.event.ActionEvent; 9 | import java.net.SocketException; 10 | 11 | 12 | public class BeanCanFrameManager extends BeanCanFrame implements ProtocolEventListener, CallManager { 13 | 14 | private Call _ca = null; 15 | private Friend _peer = null; 16 | private String _username = ""; 17 | private String _password = ""; 18 | private String _host = ""; 19 | private Binder _bind = null; 20 | private boolean _isApplet = false; 21 | private AudioInterface _audioBase = null; 22 | 23 | public BeanCanFrameManager(boolean isApplet, int level, String host) { 24 | super(); 25 | Log.setLevel(level); 26 | _isApplet = isApplet; 27 | _host = host; 28 | } 29 | 30 | public void start() { 31 | this.setVisible(true); 32 | _audioBase = new Audio8k(); 33 | try { 34 | _bind = new BinderSE(_host, _audioBase); 35 | } catch (SocketException ex) { 36 | status.setText(ex.getMessage()); 37 | } 38 | 39 | } 40 | 41 | public void stop() { 42 | if (_bind != null) { 43 | _bind.stop(); 44 | } 45 | this.hide(); 46 | status.setText("Stopped"); 47 | _bind = null; 48 | } 49 | 50 | public BeanCanFrameManager(String username, String password, String host, boolean isApplet, int level) { 51 | this(isApplet, level, host); 52 | _username = username; 53 | _password = password; 54 | } 55 | 56 | void register() { 57 | if (_bind == null) { 58 | start(); 59 | } 60 | try { 61 | 62 | _bind.register(_username, _password, this, true); 63 | } catch (Exception ex) { 64 | status.setText(ex.getMessage()); 65 | } 66 | } 67 | 68 | /** 69 | * newCall 70 | * 71 | * @param c Call 72 | */ 73 | @Override 74 | public void newCall(Call c) { 75 | Log.debug("Llamada Entrante "); 76 | if (_ca == null) { 77 | _ca = c; 78 | Log.debug("_ca == null :" + _ca.getStatus()); 79 | this.status.setText(c.getStatus()); 80 | if (_ca.getIsInbound()) { 81 | act.setText("Atender"); 82 | } else { 83 | act.setText("Cortar"); 84 | } 85 | } else { 86 | Log.debug("_ca != null :" + _ca.getStatus()); 87 | this.status.setText("Ignorando llamada Entrante"); 88 | } 89 | } 90 | 91 | /** 92 | * registered 93 | * 94 | * @param f Friend 95 | * @param s boolean 96 | */ 97 | @Override 98 | public void registered(Friend f, boolean s) { 99 | _peer = f; 100 | this.status.setText(_peer.getStatus()); 101 | } 102 | 103 | 104 | @Override 105 | public boolean accept(Call ca) { 106 | Log.debug("Aceptada Entrante "); 107 | boolean ret = true; 108 | if (_ca != null) { 109 | ret = false; 110 | } 111 | return ret; 112 | } 113 | 114 | 115 | /** 116 | * hungUp 117 | * 118 | * @param c Call 119 | */ 120 | @Override 121 | public void hungUp(Call c) { 122 | _ca = null; 123 | status.setText("Disponible"); 124 | act.setText("Llamar"); 125 | } 126 | 127 | /** 128 | * ringing 129 | * 130 | * @param c Call 131 | */ 132 | @Override 133 | public void ringing(Call c) { 134 | status.setText("Ringing"); 135 | } 136 | 137 | /** 138 | * Lets us know that the call we made is answered (or 139 | * not). 140 | * 141 | * @param c Call 142 | * @see ProtocolEventListener#answered(Call) 143 | */ 144 | @Override 145 | public void answered(Call c) { 146 | status.setText("Antendida " + c.isAnswered()); 147 | } 148 | 149 | /** 150 | * Called when it is known whether or not friend can reach its host 151 | * (PBX). 152 | * 153 | * @param f Friend 154 | * @param b Whether friend can reach its host 155 | * @param roundtrip The round trip (ms) of the request 156 | * @todo implement 157 | */ 158 | @Override 159 | public void setHostReachable(Friend f, boolean b, int roundtrip) { 160 | Log.warn("setHostReachable " + b + ", roundtrip " + roundtrip); 161 | } 162 | 163 | /** 164 | */ 165 | @Override 166 | void dialString_actionPerformed(ActionEvent e) { 167 | if (_ca == null) { 168 | if (_peer != null) { 169 | String num = dialString.getText(); 170 | _peer.newCall(_username, _password, num, null, null); 171 | } 172 | } else { 173 | if (_ca.getIsInbound()) { 174 | if (_ca.isAnswered()) { 175 | _ca.hangup(); 176 | } else { 177 | _ca.answer(); 178 | act.setText("Cortar"); 179 | } 180 | } else { 181 | _ca.hangup(); 182 | } 183 | } 184 | } 185 | 186 | 187 | @Override 188 | void button_action(ActionEvent e) { 189 | if (_ca == null) { 190 | super.button_action(e); 191 | } else { 192 | String t = e.getActionCommand(); 193 | _ca.sendDTMF(t.charAt(0)); 194 | status.setText("Enviado dtmf " + t); 195 | } 196 | } 197 | 198 | @Override 199 | void hold() { 200 | if (_ca != null) { 201 | _ca.hold(); 202 | } 203 | } 204 | 205 | @Override 206 | void clear_actionPerformed(ActionEvent e) { 207 | dialString.setText(""); 208 | } 209 | 210 | public String get_host() { 211 | return _host; 212 | } 213 | 214 | public String get_password() { 215 | return _password; 216 | } 217 | 218 | public String get_username() { 219 | return _username; 220 | } 221 | 222 | public void set_username(String _username) { 223 | this._username = _username; 224 | } 225 | 226 | public void set_password(String _password) { 227 | this._password = _password; 228 | } 229 | 230 | public void set_host(String _host) { 231 | this._host = _host; 232 | } 233 | 234 | /** 235 | * set_debug 236 | * 237 | * @param debug int 238 | */ 239 | public void set_debug(int debug) { 240 | Log.setLevel(debug); 241 | } 242 | 243 | } 244 | -------------------------------------------------------------------------------- /src/main/java/org/asteriskjava/iax/ui/GuiEventSender.java: -------------------------------------------------------------------------------- 1 | 2 | package org.asteriskjava.iax.ui; 3 | 4 | import org.asteriskjava.iax.protocol.Call; 5 | import org.asteriskjava.iax.protocol.Friend; 6 | import org.asteriskjava.iax.protocol.ProtocolEventListener; 7 | 8 | /** 9 | * Decouples events from the main threads. This class it used by Friend. 10 | */ 11 | 12 | public class GuiEventSender implements ProtocolEventListener { 13 | 14 | private ProtocolEventListener _gui; 15 | private Call _call; 16 | 17 | /** 18 | * Constructor for the GuiEventSender object 19 | * 20 | * @param gui The protocol event listener 21 | */ 22 | public GuiEventSender(ProtocolEventListener gui) { 23 | _gui = gui; 24 | } 25 | 26 | /** 27 | * Received a new call. 28 | * Via invokeLater() this is passed on to the ProtocolEventListener parameter. 29 | * 30 | * @param c The call object 31 | */ 32 | public void newCall(Call c) { 33 | _call = c; 34 | Runnable r = new Runnable() { 35 | public void run() { 36 | if (_gui != null) { 37 | _gui.newCall(_call); 38 | } 39 | } 40 | }; 41 | javax.swing.SwingUtilities.invokeLater(r); 42 | } 43 | 44 | /** 45 | * Hung up. 46 | * Via invokeLater() this is passed on to the ProtocolEventListener parameter. 47 | * 48 | * @param c The call object 49 | */ 50 | public void hungUp(Call c) { 51 | _call = c; 52 | Runnable r = new Runnable() { 53 | public void run() { 54 | if (_gui != null) { 55 | _gui.hungUp(_call); 56 | } 57 | } 58 | }; 59 | javax.swing.SwingUtilities.invokeLater(r); 60 | } 61 | 62 | /** 63 | * Ringing. 64 | * Via invokeLater() this is passed on to the ProtocolEventListener parameter. 65 | * 66 | * @param c The call object 67 | */ 68 | public void ringing(Call c) { 69 | _call = c; 70 | Runnable r = new Runnable() { 71 | public void run() { 72 | if (_gui != null) { 73 | _gui.ringing(_call); 74 | } 75 | } 76 | }; 77 | javax.swing.SwingUtilities.invokeLater(r); 78 | } 79 | 80 | /** 81 | * Answered. 82 | * Via invokeLater() this is passed on to the ProtocolEventListener parameter. 83 | * 84 | * @param c The call object 85 | */ 86 | public void answered(Call c) { 87 | _call = c; 88 | Runnable r = new Runnable() { 89 | public void run() { 90 | if (_gui != null) { 91 | _gui.answered(_call); 92 | } 93 | } 94 | }; 95 | javax.swing.SwingUtilities.invokeLater(r); 96 | } 97 | 98 | /** 99 | * registered 100 | * 101 | * @param f Friend 102 | * @param s boolean 103 | */ 104 | public void registered(Friend f, boolean s) { 105 | final Friend ff = f; 106 | final boolean fs = s; 107 | Runnable r = new Runnable() { 108 | public void run() { 109 | if (_gui != null) { 110 | _gui.registered(ff, fs); 111 | } 112 | } 113 | }; 114 | javax.swing.SwingUtilities.invokeLater(r); 115 | } 116 | 117 | /** 118 | * setHostReachable 119 | * 120 | * @param f Friend 121 | * @param b boolean 122 | * @param roundtrip int 123 | */ 124 | public void setHostReachable(Friend f, boolean b, int roundtrip) { 125 | final Friend ff = f; 126 | final boolean fb = b; 127 | final int fr = roundtrip; 128 | Runnable r = new Runnable() { 129 | public void run() { 130 | if (_gui != null) { 131 | _gui.setHostReachable(ff, fb, fr); 132 | } 133 | } 134 | }; 135 | javax.swing.SwingUtilities.invokeLater(r); 136 | 137 | } 138 | 139 | } 140 | -------------------------------------------------------------------------------- /src/main/java/org/asteriskjava/iax/util/ByteBuffer.java: -------------------------------------------------------------------------------- 1 | package org.asteriskjava.iax.util; 2 | 3 | public class ByteBuffer { 4 | private byte[] myStore = null; // My backing store 5 | private int pos = 0; // Position index 6 | private int offset = 0; // into backing store to enable slicing 7 | 8 | /** 9 | * allocate 10 | * 11 | * @param i int 12 | * @return ByteBuffer 13 | */ 14 | public static ByteBuffer allocate(int i) { 15 | ByteBuffer bb = new ByteBuffer(); 16 | bb.myStore = new byte[i]; 17 | bb.pos = 0; 18 | bb.offset = 0; 19 | return bb; 20 | } 21 | 22 | /** 23 | * wrap 24 | * 25 | * @param bs byte[] 26 | * @return ByteBuffer 27 | */ 28 | public static ByteBuffer wrap(byte[] bs) { 29 | ByteBuffer bb = new ByteBuffer(); 30 | bb.myStore = bs; 31 | bb.pos = 0; 32 | bb.offset = 0; 33 | return bb; 34 | } 35 | 36 | /** 37 | * slice 38 | * 39 | * @return ByteBuffer 40 | */ 41 | public ByteBuffer slice() { 42 | ByteBuffer bb = new ByteBuffer(); 43 | bb.myStore = myStore; 44 | bb.pos = 0; 45 | bb.offset = pos; 46 | return bb; 47 | } 48 | 49 | /** 50 | * array 51 | * 52 | * @return byte[] 53 | */ 54 | public byte[] array() { 55 | if (offset != 0) { 56 | throw new java.lang.IllegalStateException(); 57 | } 58 | return myStore; 59 | } 60 | 61 | /** 62 | * position 63 | * 64 | * @return int 65 | */ 66 | public int position() { 67 | return pos; 68 | } 69 | 70 | /** 71 | * getShort 72 | * 73 | * @return short 74 | */ 75 | public short getShort() { 76 | if (offset + pos + 2 > myStore.length) { 77 | throw new IndexOutOfBoundsException(); 78 | } 79 | short s = (short) ((myStore[offset + pos] << 8) + 80 | (myStore[offset + pos + 1] & 0xFF)); 81 | pos += 2; 82 | return s; 83 | } 84 | 85 | public short getShort(int of) { 86 | if (offset + of + 2 > myStore.length) { 87 | throw new IndexOutOfBoundsException(); 88 | } 89 | short s = (short) ((myStore[offset + of] << 8) + 90 | (myStore[offset + of + 1] & 0xFF)); 91 | return s; 92 | } 93 | 94 | /** 95 | * getInt 96 | * 97 | * @return int 98 | */ 99 | public int getInt() { 100 | if (offset + pos + 4 > myStore.length) { 101 | throw new IndexOutOfBoundsException(); 102 | } 103 | int i = (myStore[offset + pos] << 24) 104 | + ((myStore[offset + pos + 1] & 0xFF) << 16) 105 | + ((myStore[offset + pos + 2] & 0xFF) << 8) 106 | + (myStore[offset + pos + 3] & 0xFF); 107 | pos += 4; 108 | return i; 109 | } 110 | 111 | /** 112 | * get 113 | * 114 | * @return byte 115 | */ 116 | public byte get() { 117 | if (offset + pos + 1 > myStore.length) { 118 | throw new IndexOutOfBoundsException(); 119 | } 120 | return myStore[offset + pos++]; 121 | } 122 | 123 | /** 124 | * putChar 125 | * 126 | * @param c char 127 | */ 128 | public void putChar(char c) { 129 | if (offset + pos + 2 > myStore.length) { 130 | throw new IndexOutOfBoundsException(); 131 | } 132 | myStore[offset + pos++] = (byte) (((short) c) >> 8); 133 | myStore[offset + pos++] = (byte) c; 134 | } 135 | 136 | /** 137 | * putChar 138 | * 139 | * @param i int 140 | * @param c char 141 | */ 142 | public void putChar(int i, char c) { 143 | if (offset + i + 2 > myStore.length) { 144 | throw new IndexOutOfBoundsException(); 145 | } 146 | myStore[offset + i] = (byte) (((short) c) >> 8); 147 | myStore[offset + i + 1] = (byte) c; 148 | } 149 | 150 | /** 151 | * putInt 152 | * 153 | * @param i int 154 | */ 155 | public void putInt(int i) { 156 | if (offset + pos + 4 > myStore.length) { 157 | throw new IndexOutOfBoundsException(); 158 | } 159 | myStore[offset + pos++] = (byte) (i >> 24); 160 | myStore[offset + pos++] = (byte) ((i >> 16) & 0xff); 161 | myStore[offset + pos++] = (byte) ((i >> 8) & 0xff); 162 | myStore[offset + pos++] = (byte) (i & 0xff); 163 | } 164 | 165 | /** 166 | * put 167 | * 168 | * @param b byte 169 | */ 170 | public void put(byte b) { 171 | if (offset + pos + 1 > myStore.length) { 172 | throw new IndexOutOfBoundsException(); 173 | } 174 | myStore[pos] = b; 175 | pos++; 176 | } 177 | 178 | /** 179 | * put 180 | * 181 | * @param payload byte[] 182 | */ 183 | public void put(byte[] payload) { 184 | if (offset + pos + payload.length > myStore.length) { 185 | throw new IndexOutOfBoundsException(); 186 | } 187 | System.arraycopy(payload, 0, myStore, offset + pos, payload.length); 188 | pos += payload.length; 189 | } 190 | 191 | /** 192 | * getChar 193 | * 194 | * @return char 195 | */ 196 | public char getChar() { 197 | if (offset + pos + 2 > myStore.length) { 198 | throw new IndexOutOfBoundsException(); 199 | } 200 | short s = (short) ((myStore[offset + pos] << 8) + 201 | (myStore[offset + pos + 1] & 0xFF)); 202 | pos += 2; 203 | return (char) s; 204 | } 205 | 206 | /** 207 | * getChar 208 | * 209 | * @param i int 210 | * @return char 211 | */ 212 | public char getChar(int i) { 213 | if (offset + i + 2 > myStore.length) { 214 | throw new IndexOutOfBoundsException(); 215 | } 216 | short s = (short) ((myStore[offset + i] << 8) + 217 | (myStore[offset + i + 1] & 0xFF)); 218 | return (char) s; 219 | } 220 | 221 | /** 222 | * get 223 | * 224 | * @param b byte[] 225 | */ 226 | public void get(byte[] b) { 227 | int l = remaining(); 228 | if (l > b.length) { 229 | l = b.length; 230 | } 231 | System.arraycopy(myStore, offset + pos, b, 0, l); 232 | pos += l; 233 | } 234 | 235 | /** 236 | * remaining 237 | * 238 | * @return int 239 | */ 240 | public int remaining() { 241 | return myStore.length - offset - pos; 242 | } 243 | 244 | /** 245 | * putShort 246 | * 247 | * @param s short 248 | */ 249 | public void putShort(short s) { 250 | if (offset + pos + 2 > myStore.length) { 251 | throw new IndexOutOfBoundsException(); 252 | } 253 | myStore[offset + pos++] = (byte) (s >> 8); 254 | myStore[offset + pos++] = (byte) (s & 0xff); 255 | } 256 | 257 | public void putShort(int of, short s) { 258 | if (offset + of + 2 > myStore.length) { 259 | throw new IndexOutOfBoundsException(); 260 | } 261 | myStore[offset + of++] = (byte) (s >> 8); 262 | myStore[offset + of++] = (byte) (s & 0xff); 263 | } 264 | 265 | public boolean hasRemaining() { 266 | return (offset + pos < myStore.length); 267 | } 268 | } 269 | -------------------------------------------------------------------------------- /src/main/java/org/asteriskjava/iax/util/DTMFGenerator.java: -------------------------------------------------------------------------------- 1 | package org.asteriskjava.iax.util; 2 | 3 | 4 | import javax.sound.sampled.*; 5 | 6 | 7 | public class DTMFGenerator { 8 | 9 | private int NUM_BANDS = 10; 10 | 11 | private float frequencyArray[] = {697.0F, 770.0F, 852.0F, 941.0F, 1209.0F, 1336.0F, 1477.0F, 1633.0F, 440.0F, 523.25F}; 12 | 13 | private float Q1[] = new float[NUM_BANDS]; 14 | private float Q2[] = new float[NUM_BANDS]; 15 | private float freqCoeffValueArray[] = new float[NUM_BANDS]; 16 | private static boolean ringing = true; 17 | 18 | public void init(float sps) { 19 | for (int i = 0; i < NUM_BANDS; ++i) { 20 | Q1[i] = (float) java.lang.Math.sin(0.0F); 21 | Q2[i] = (float) java.lang.Math.sin(2.0F * java.lang.Math.PI * frequencyArray[i] / sps); 22 | freqCoeffValueArray[i] = (float) (2 * java.lang.Math.cos(2.0F * java.lang.Math.PI * frequencyArray[i] / sps)); 23 | } 24 | } 25 | 26 | public float getLow(String chr) { 27 | int idx = 0; 28 | if ("1".equals(chr)) { 29 | idx = 0; 30 | } else if ("2".equals(chr)) { 31 | idx = 0; 32 | } else if ("3".equals(chr)) { 33 | idx = 0; 34 | } else if ("4".equals(chr)) { 35 | idx = 1; 36 | } else if ("5".equals(chr)) { 37 | idx = 1; 38 | } else if ("6".equals(chr)) { 39 | idx = 1; 40 | } else if ("7".equals(chr)) { 41 | idx = 2; 42 | } else if ("8".equals(chr)) { 43 | idx = 2; 44 | } else if ("9".equals(chr)) { 45 | idx = 2; 46 | } else if ("*".equals(chr)) { 47 | idx = 3; 48 | } else if ("0".equals(chr)) { 49 | idx = 3; 50 | } else if ("#".equals(chr)) { 51 | idx = 3; 52 | } else if ("Ring".equals(chr)) { 53 | idx = 8; 54 | } 55 | float g; 56 | g = Q1[idx]; 57 | Q1[idx] = Q2[idx]; 58 | Q2[idx] = freqCoeffValueArray[idx] * Q1[idx] - g; 59 | return g; 60 | } 61 | 62 | public float getHigh(String chr) { 63 | int idx = 0; 64 | if ("1".equals(chr)) { 65 | idx = 4; 66 | } else if ("2".equals(chr)) { 67 | idx = 5; 68 | } else if ("3".equals(chr)) { 69 | idx = 6; 70 | } else if ("4".equals(chr)) { 71 | idx = 4; 72 | } else if ("5".equals(chr)) { 73 | idx = 5; 74 | } else if ("6".equals(chr)) { 75 | idx = 6; 76 | } else if ("7".equals(chr)) { 77 | idx = 4; 78 | } else if ("8".equals(chr)) { 79 | idx = 5; 80 | } else if ("9".equals(chr)) { 81 | idx = 6; 82 | } else if ("*".equals(chr)) { 83 | idx = 4; 84 | } else if ("0".equals(chr)) { 85 | idx = 5; 86 | } else if ("#".equals(chr)) { 87 | idx = 6; 88 | } else if ("Ring".equals(chr)) { 89 | idx = 9; 90 | } 91 | float g; 92 | g = Q1[idx]; 93 | Q1[idx] = Q2[idx]; 94 | Q2[idx] = freqCoeffValueArray[idx] * Q1[idx] - g; 95 | return g; 96 | } 97 | 98 | public float getDTMF(String chr) { 99 | return getLow(chr) + getHigh(chr); 100 | } 101 | 102 | public static void StopRing() { 103 | ringing = false; 104 | } 105 | 106 | 107 | public static void playRing() { 108 | ringing = true; 109 | Thread ring = new Thread() { 110 | 111 | @Override 112 | public void run() { 113 | while (ringing) { 114 | try { 115 | DTMFGenerator generator = new DTMFGenerator(); 116 | generator.init(8000.0F); 117 | AudioFormat pcmFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 8000.0F, 8, 1, 1, 8000.0F, false); 118 | DataLine.Info info = new DataLine.Info(SourceDataLine.class, pcmFormat); 119 | SourceDataLine line = (SourceDataLine) AudioSystem.getLine(info); 120 | line.open(pcmFormat); 121 | line.start(); 122 | byte[] abData = new byte[160]; 123 | for (int i = 0; i < 150; ++i) { 124 | int available = line.available(); 125 | if (available < 1600) { 126 | Thread.sleep(150); 127 | } else { 128 | if (i < 50) { 129 | for (int j = 0; j < 160; ++j) { 130 | if ((i % 2) == 0) { 131 | abData[j] = (byte) ((generator.getLow("Ring") * 128.0F) * 0.1); 132 | } else { 133 | abData[j] = (byte) ((generator.getHigh("Ring") * 128.0F) * 0.1); 134 | } 135 | } 136 | } else { 137 | for (int j = 0; j < 160; ++j) { 138 | abData[j] = (byte) 0; 139 | } 140 | } 141 | line.write(abData, 0, abData.length); 142 | } 143 | } 144 | line.drain(); 145 | line.close(); 146 | } catch (LineUnavailableException e) { 147 | e.printStackTrace(); 148 | } catch (InterruptedException e) { 149 | e.printStackTrace(); 150 | } 151 | } 152 | } 153 | }; 154 | ring.start(); 155 | } 156 | 157 | 158 | public static void playTone(final String tone) { 159 | Thread toneThread = new Thread() { 160 | @Override 161 | public void run() { 162 | try { 163 | DTMFGenerator generator = new DTMFGenerator(); 164 | generator.init(8000.0F); 165 | AudioFormat pcmFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 8000.0F, 8, 1, 1, 8000.0F, false); 166 | DataLine.Info info = new DataLine.Info(SourceDataLine.class, pcmFormat); 167 | SourceDataLine line = (SourceDataLine) AudioSystem.getLine(info); 168 | line.open(pcmFormat); 169 | line.start(); 170 | byte[] abData = new byte[160]; 171 | for (int i = 0; i < 10; ++i) { 172 | int available = line.available(); 173 | if (available < 1600) { 174 | Thread.sleep(150); 175 | } else { 176 | for (int j = 0; j < 160; ++j) { 177 | abData[j] = (byte) ((generator.getDTMF(tone) * 128.0F) * 0.1); 178 | } 179 | line.write(abData, 0, abData.length); 180 | } 181 | } 182 | line.drain(); 183 | line.close(); 184 | } catch (LineUnavailableException e) { 185 | e.printStackTrace(); 186 | } catch (InterruptedException e) { 187 | e.printStackTrace(); 188 | } 189 | } 190 | }; 191 | toneThread.start(); 192 | } 193 | 194 | } 195 | -------------------------------------------------------------------------------- /src/main/java/org/asteriskjava/iax/util/GeneralDigest.java: -------------------------------------------------------------------------------- 1 | package org.asteriskjava.iax.util; 2 | 3 | 4 | /** 5 | * base implementation of MD4 family style digest as outlined in 6 | * "Handbook of Applied Cryptography", pages 344 - 347. 7 | */ 8 | public abstract class GeneralDigest { 9 | private byte[] xBuf = new byte[4]; 10 | private int xBufOff = 0; 11 | 12 | private long byteCount; 13 | 14 | /** 15 | * Standard constructor 16 | */ 17 | protected GeneralDigest() { 18 | } 19 | 20 | /** 21 | * Copy constructor. We are using copy constructors in place 22 | * of the Object.clone() interface as this interface is not 23 | * supported by J2ME. 24 | */ 25 | protected GeneralDigest(GeneralDigest t) { 26 | System.arraycopy(t.xBuf, 0, xBuf, 0, t.xBuf.length); 27 | xBufOff = t.xBufOff; 28 | byteCount = t.byteCount; 29 | } 30 | 31 | public void update( 32 | byte in) { 33 | xBuf[xBufOff++] = in; 34 | 35 | if (xBufOff == xBuf.length) { 36 | processWord(xBuf, 0); 37 | xBufOff = 0; 38 | } 39 | 40 | byteCount++; 41 | } 42 | 43 | public void update( 44 | byte[] in, 45 | int inOff, 46 | int len) { 47 | // 48 | // fill the current word 49 | // 50 | while ((xBufOff != 0) && (len > 0)) { 51 | update(in[inOff]); 52 | 53 | inOff++; 54 | len--; 55 | } 56 | 57 | // 58 | // process whole words. 59 | // 60 | while (len > 4) { 61 | processWord(in, inOff); 62 | 63 | inOff += 4; 64 | len -= 4; 65 | byteCount += 4; 66 | } 67 | 68 | // 69 | // load in the remainder. 70 | // 71 | while (len > 0) { 72 | update(in[inOff]); 73 | 74 | inOff++; 75 | len--; 76 | } 77 | } 78 | 79 | public void finish() { 80 | long bitLength = (byteCount << 3); 81 | 82 | // 83 | // add the pad bytes. 84 | // 85 | update((byte) 128); 86 | 87 | while (xBufOff != 0) { 88 | update((byte) 0); 89 | } 90 | 91 | processLength(bitLength); 92 | 93 | processBlock(); 94 | } 95 | 96 | public void reset() { 97 | byteCount = 0; 98 | 99 | xBufOff = 0; 100 | xBuf[0] = xBuf[1] = xBuf[2] = xBuf[3] = 0; 101 | } 102 | 103 | protected abstract void processWord(byte[] in, int inOff); 104 | 105 | protected abstract void processLength(long bitLength); 106 | 107 | protected abstract void processBlock(); 108 | } 109 | -------------------------------------------------------------------------------- /src/main/java/org/asteriskjava/iax/util/MD5Digest.java: -------------------------------------------------------------------------------- 1 | package org.asteriskjava.iax.util; 2 | 3 | 4 | /** 5 | * implementation of MD5 as outlined in "Handbook of Applied Cryptography", pages 346 - 347. 6 | */ 7 | public class MD5Digest 8 | extends GeneralDigest { 9 | private static final int DIGEST_LENGTH = 16; 10 | 11 | private int H1, H2, H3, H4; // IV's 12 | 13 | private int[] X = new int[16]; 14 | private int xOff; 15 | 16 | /** 17 | * Standard constructor 18 | */ 19 | public MD5Digest() { 20 | reset(); 21 | } 22 | 23 | /** 24 | * Copy constructor. This will copy the state of the provided 25 | * message digest. 26 | */ 27 | public MD5Digest(MD5Digest t) { 28 | super(t); 29 | 30 | H1 = t.H1; 31 | H2 = t.H2; 32 | H3 = t.H3; 33 | H4 = t.H4; 34 | 35 | System.arraycopy(t.X, 0, X, 0, t.X.length); 36 | xOff = t.xOff; 37 | } 38 | 39 | public String getAlgorithmName() { 40 | return "MD5"; 41 | } 42 | 43 | public int getDigestSize() { 44 | return DIGEST_LENGTH; 45 | } 46 | 47 | @Override 48 | protected void processWord( 49 | byte[] in, 50 | int inOff) { 51 | X[xOff++] = (in[inOff] & 0xff) | ((in[inOff + 1] & 0xff) << 8) 52 | | ((in[inOff + 2] & 0xff) << 16) | ((in[inOff + 3] & 0xff) << 24); 53 | 54 | if (xOff == 16) { 55 | processBlock(); 56 | } 57 | } 58 | 59 | @Override 60 | protected void processLength( 61 | long bitLength) { 62 | if (xOff > 14) { 63 | processBlock(); 64 | } 65 | 66 | X[14] = (int) (bitLength & 0xffffffff); 67 | X[15] = (int) (bitLength >>> 32); 68 | } 69 | 70 | private void unpackWord( 71 | int word, 72 | byte[] out, 73 | int outOff) { 74 | out[outOff] = (byte) word; 75 | out[outOff + 1] = (byte) (word >>> 8); 76 | out[outOff + 2] = (byte) (word >>> 16); 77 | out[outOff + 3] = (byte) (word >>> 24); 78 | } 79 | 80 | public int doFinal( 81 | byte[] out, 82 | int outOff) { 83 | finish(); 84 | 85 | unpackWord(H1, out, outOff); 86 | unpackWord(H2, out, outOff + 4); 87 | unpackWord(H3, out, outOff + 8); 88 | unpackWord(H4, out, outOff + 12); 89 | 90 | reset(); 91 | 92 | return DIGEST_LENGTH; 93 | } 94 | 95 | /** 96 | * reset the chaining variables to the IV values. 97 | */ 98 | @Override 99 | public void reset() { 100 | super.reset(); 101 | 102 | H1 = 0x67452301; 103 | H2 = 0xefcdab89; 104 | H3 = 0x98badcfe; 105 | H4 = 0x10325476; 106 | 107 | xOff = 0; 108 | 109 | for (int i = 0; i != X.length; i++) { 110 | X[i] = 0; 111 | } 112 | } 113 | 114 | // 115 | // round 1 left rotates 116 | // 117 | private static final int S11 = 7; 118 | private static final int S12 = 12; 119 | private static final int S13 = 17; 120 | private static final int S14 = 22; 121 | 122 | // 123 | // round 2 left rotates 124 | // 125 | private static final int S21 = 5; 126 | private static final int S22 = 9; 127 | private static final int S23 = 14; 128 | private static final int S24 = 20; 129 | 130 | // 131 | // round 3 left rotates 132 | // 133 | private static final int S31 = 4; 134 | private static final int S32 = 11; 135 | private static final int S33 = 16; 136 | private static final int S34 = 23; 137 | 138 | // 139 | // round 4 left rotates 140 | // 141 | private static final int S41 = 6; 142 | private static final int S42 = 10; 143 | private static final int S43 = 15; 144 | private static final int S44 = 21; 145 | 146 | /* 147 | * rotate int x left n bits. 148 | */ 149 | private int rotateLeft( 150 | int x, 151 | int n) { 152 | return (x << n) | (x >>> (32 - n)); 153 | } 154 | 155 | /* 156 | * F, G, H and I are the basic MD5 functions. 157 | */ 158 | private int F( 159 | int u, 160 | int v, 161 | int w) { 162 | return (u & v) | (~u & w); 163 | } 164 | 165 | private int G( 166 | int u, 167 | int v, 168 | int w) { 169 | return (u & w) | (v & ~w); 170 | } 171 | 172 | private int H( 173 | int u, 174 | int v, 175 | int w) { 176 | return u ^ v ^ w; 177 | } 178 | 179 | private int K( 180 | int u, 181 | int v, 182 | int w) { 183 | return v ^ (u | ~w); 184 | } 185 | 186 | @Override 187 | protected void processBlock() { 188 | int a = H1; 189 | int b = H2; 190 | int c = H3; 191 | int d = H4; 192 | 193 | // 194 | // Round 1 - F cycle, 16 times. 195 | // 196 | a = rotateLeft((a + F(b, c, d) + X[0] + 0xd76aa478), S11) + b; 197 | d = rotateLeft((d + F(a, b, c) + X[1] + 0xe8c7b756), S12) + a; 198 | c = rotateLeft((c + F(d, a, b) + X[2] + 0x242070db), S13) + d; 199 | b = rotateLeft((b + F(c, d, a) + X[3] + 0xc1bdceee), S14) + c; 200 | a = rotateLeft((a + F(b, c, d) + X[4] + 0xf57c0faf), S11) + b; 201 | d = rotateLeft((d + F(a, b, c) + X[5] + 0x4787c62a), S12) + a; 202 | c = rotateLeft((c + F(d, a, b) + X[6] + 0xa8304613), S13) + d; 203 | b = rotateLeft((b + F(c, d, a) + X[7] + 0xfd469501), S14) + c; 204 | a = rotateLeft((a + F(b, c, d) + X[8] + 0x698098d8), S11) + b; 205 | d = rotateLeft((d + F(a, b, c) + X[9] + 0x8b44f7af), S12) + a; 206 | c = rotateLeft((c + F(d, a, b) + X[10] + 0xffff5bb1), S13) + d; 207 | b = rotateLeft((b + F(c, d, a) + X[11] + 0x895cd7be), S14) + c; 208 | a = rotateLeft((a + F(b, c, d) + X[12] + 0x6b901122), S11) + b; 209 | d = rotateLeft((d + F(a, b, c) + X[13] + 0xfd987193), S12) + a; 210 | c = rotateLeft((c + F(d, a, b) + X[14] + 0xa679438e), S13) + d; 211 | b = rotateLeft((b + F(c, d, a) + X[15] + 0x49b40821), S14) + c; 212 | 213 | // 214 | // Round 2 - G cycle, 16 times. 215 | // 216 | a = rotateLeft((a + G(b, c, d) + X[1] + 0xf61e2562), S21) + b; 217 | d = rotateLeft((d + G(a, b, c) + X[6] + 0xc040b340), S22) + a; 218 | c = rotateLeft((c + G(d, a, b) + X[11] + 0x265e5a51), S23) + d; 219 | b = rotateLeft((b + G(c, d, a) + X[0] + 0xe9b6c7aa), S24) + c; 220 | a = rotateLeft((a + G(b, c, d) + X[5] + 0xd62f105d), S21) + b; 221 | d = rotateLeft((d + G(a, b, c) + X[10] + 0x02441453), S22) + a; 222 | c = rotateLeft((c + G(d, a, b) + X[15] + 0xd8a1e681), S23) + d; 223 | b = rotateLeft((b + G(c, d, a) + X[4] + 0xe7d3fbc8), S24) + c; 224 | a = rotateLeft((a + G(b, c, d) + X[9] + 0x21e1cde6), S21) + b; 225 | d = rotateLeft((d + G(a, b, c) + X[14] + 0xc33707d6), S22) + a; 226 | c = rotateLeft((c + G(d, a, b) + X[3] + 0xf4d50d87), S23) + d; 227 | b = rotateLeft((b + G(c, d, a) + X[8] + 0x455a14ed), S24) + c; 228 | a = rotateLeft((a + G(b, c, d) + X[13] + 0xa9e3e905), S21) + b; 229 | d = rotateLeft((d + G(a, b, c) + X[2] + 0xfcefa3f8), S22) + a; 230 | c = rotateLeft((c + G(d, a, b) + X[7] + 0x676f02d9), S23) + d; 231 | b = rotateLeft((b + G(c, d, a) + X[12] + 0x8d2a4c8a), S24) + c; 232 | 233 | // 234 | // Round 3 - H cycle, 16 times. 235 | // 236 | a = rotateLeft((a + H(b, c, d) + X[5] + 0xfffa3942), S31) + b; 237 | d = rotateLeft((d + H(a, b, c) + X[8] + 0x8771f681), S32) + a; 238 | c = rotateLeft((c + H(d, a, b) + X[11] + 0x6d9d6122), S33) + d; 239 | b = rotateLeft((b + H(c, d, a) + X[14] + 0xfde5380c), S34) + c; 240 | a = rotateLeft((a + H(b, c, d) + X[1] + 0xa4beea44), S31) + b; 241 | d = rotateLeft((d + H(a, b, c) + X[4] + 0x4bdecfa9), S32) + a; 242 | c = rotateLeft((c + H(d, a, b) + X[7] + 0xf6bb4b60), S33) + d; 243 | b = rotateLeft((b + H(c, d, a) + X[10] + 0xbebfbc70), S34) + c; 244 | a = rotateLeft((a + H(b, c, d) + X[13] + 0x289b7ec6), S31) + b; 245 | d = rotateLeft((d + H(a, b, c) + X[0] + 0xeaa127fa), S32) + a; 246 | c = rotateLeft((c + H(d, a, b) + X[3] + 0xd4ef3085), S33) + d; 247 | b = rotateLeft((b + H(c, d, a) + X[6] + 0x04881d05), S34) + c; 248 | a = rotateLeft((a + H(b, c, d) + X[9] + 0xd9d4d039), S31) + b; 249 | d = rotateLeft((d + H(a, b, c) + X[12] + 0xe6db99e5), S32) + a; 250 | c = rotateLeft((c + H(d, a, b) + X[15] + 0x1fa27cf8), S33) + d; 251 | b = rotateLeft((b + H(c, d, a) + X[2] + 0xc4ac5665), S34) + c; 252 | 253 | // 254 | // Round 4 - K cycle, 16 times. 255 | // 256 | a = rotateLeft((a + K(b, c, d) + X[0] + 0xf4292244), S41) + b; 257 | d = rotateLeft((d + K(a, b, c) + X[7] + 0x432aff97), S42) + a; 258 | c = rotateLeft((c + K(d, a, b) + X[14] + 0xab9423a7), S43) + d; 259 | b = rotateLeft((b + K(c, d, a) + X[5] + 0xfc93a039), S44) + c; 260 | a = rotateLeft((a + K(b, c, d) + X[12] + 0x655b59c3), S41) + b; 261 | d = rotateLeft((d + K(a, b, c) + X[3] + 0x8f0ccc92), S42) + a; 262 | c = rotateLeft((c + K(d, a, b) + X[10] + 0xffeff47d), S43) + d; 263 | b = rotateLeft((b + K(c, d, a) + X[1] + 0x85845dd1), S44) + c; 264 | a = rotateLeft((a + K(b, c, d) + X[8] + 0x6fa87e4f), S41) + b; 265 | d = rotateLeft((d + K(a, b, c) + X[15] + 0xfe2ce6e0), S42) + a; 266 | c = rotateLeft((c + K(d, a, b) + X[6] + 0xa3014314), S43) + d; 267 | b = rotateLeft((b + K(c, d, a) + X[13] + 0x4e0811a1), S44) + c; 268 | a = rotateLeft((a + K(b, c, d) + X[4] + 0xf7537e82), S41) + b; 269 | d = rotateLeft((d + K(a, b, c) + X[11] + 0xbd3af235), S42) + a; 270 | c = rotateLeft((c + K(d, a, b) + X[2] + 0x2ad7d2bb), S43) + d; 271 | b = rotateLeft((b + K(c, d, a) + X[9] + 0xeb86d391), S44) + c; 272 | 273 | H1 += a; 274 | H2 += b; 275 | H3 += c; 276 | H4 += d; 277 | 278 | // 279 | // reset the offset and clean out the word buffer. 280 | // 281 | xOff = 0; 282 | for (int i = 0; i != X.length; i++) { 283 | X[i] = 0; 284 | } 285 | } 286 | } 287 | -------------------------------------------------------------------------------- /src/site/apt/building.apt: -------------------------------------------------------------------------------- 1 | --- 2 | Building with Maven 3 | --- 4 | Stefan Reuter 5 | --- 6 | $Id$ 7 | 8 | Building with Maven 9 | 10 | Retrieve the latest version of Asterisk-Java IAX from SVN: 11 | 12 | --- 13 | svn co http://svn.reucon.net/repos/asterisk-java-iax/trunk asterisk-java-iax 14 | --- 15 | 16 | Then change to the created asterisk-java-iax directory and use Maven2 to 17 | build the project 18 | 19 | --- 20 | cd asterisk-java-iax 21 | mvn install 22 | --- 23 | 24 | This will create the asterisk-java-iax-${VERSION}.jar in the target subdirectory 25 | as well as in your local maven repository. -------------------------------------------------------------------------------- /src/site/apt/faq.apt: -------------------------------------------------------------------------------- 1 | --- 2 | Frequently Asked Questions 3 | --- 4 | Martin Smith 5 | --- 6 | $Id$ 7 | 8 | Frequently Asked Questions 9 | 10 | * Where is the mailing list? 11 | 12 | From {{{http://blogs.reucon.com/asterisk-java/2008/01/17/faq_where_is_the_mailing_list.html}this blog post}}: 13 | 14 | It seems we've hidden the link to our mailing lists a bit too well. 15 | 16 | We have two mailing lists: 17 | 18 | * Asterisk-Java Users for users of Asterisk-Java seeking help 19 | 20 | * Asterisk-Java Devel for developers of Asterisk-Java, i.e. the guys enhancing the library code itself. This list not intended to provide support regarding the use of Asterisk-Java. 21 | 22 | You can find the subscription details for both lists {{{http://asterisk-java.org/development/mail-lists.html}here}}. 23 | 24 | You might also be interested in our {{{http://jira.reucon.org}Bug Tracker}} where you can look for known issues, post new bug reports and submit patches. 25 | 26 | * Will Asterisk-Java IAX be included in the Asterisk-Java jar file or will it remain separate? 27 | 28 | Asterisk-Java IAX will remain a separate project for two reasons: 29 | 30 | * One of the main use cases for Asterisk-Java IAX is as an applet, so a small footprint matters 31 | 32 | * Asterisk-Java IAX is released under GPLv3 while Asterisk-Java is released unter Apache License, therefore 33 | the two projects can't be merged. 34 | 35 | -------------------------------------------------------------------------------- /src/site/apt/index.apt: -------------------------------------------------------------------------------- 1 | --- 2 | Asterisk-Java IAX 3 | --- 4 | Stefan Reuter 5 | --- 6 | $Id$ 7 | 8 | Asterisk-Java IAX 9 | 10 | Asterisk-Java IAX is a Java implementation of the IAX2 protocol as defined in 11 | {{{http://www.rfc-editor.org/authors/rfc5456.txt}RFC 5456}}. 12 | 13 | It is based on code developed by Tim Panton of {{{http://www.westhawk.co.uk}Westhawk Ltd}} for 14 | {{{http://www.mexuar.com/}Mexuar Communications}} released under GPLv3 in 2008. 15 | 16 | For now we have included a {{{demo.html}small demo page}} by Wolfgang that shows how to make use 17 | of the applet and access it from JavaScript. 18 | 19 | * License 20 | 21 | Asterisk-Java IAX is provided under the terms of the 22 | {{{http://www.gnu.org/licenses/gpl.txt}GNU General Public License, Version 3}}. 23 | 24 | The original code is Copyright 2005-2007 Mexuar Technologies Ltd. All Rights Reserved. 25 | 26 | * Status 27 | 28 | We plan to release Asterisk-Java IAX 1.0.0 as soon as possible. 29 | 30 | Ideas for the future include support for additional codecs like Speex and GSM. 31 | 32 | * Download 33 | 34 | Official releases and release candidates are available from the our 35 | {{{http://maven.reucon.com/public/org/asteriskjava/asterisk-javai-iax/}distribution site}}. 36 | 37 | The 38 | {{{http://maven.reucon.com/public-snapshot/org/asteriskjava/asterisk-java-iax/}snapshot distribution site}} 39 | hosts the latest snapshot releases. 40 | 41 | Please feel free to provide any feedback or ask for support via the 42 | {{{mail-lists.html}Asterisk-Java users mailing list}}. 43 | 44 | The latest development version of Asterisk-Java IAX is always available via SVN: 45 | 46 | +-----------------------------------------------------------------------------+ 47 | svn co http://svn.reucon.net/repos/asterisk-java-iax/trunk asterisk-java-iax 48 | +-----------------------------------------------------------------------------+ 49 | 50 | * Requirements 51 | 52 | At runtime Asterisk-Java requires a Java Runtime 53 | Environment (JRE) of at least version 1.5 (J2SE 5.0). 54 | 55 | * Related Projects 56 | 57 | {{{https://jain-sip.dev.java.net/}JAIN SIP}} contains RI, TCK, examples, tools for JAIN-SIP-1.2 58 | (JSR-32 maintenance release) and an SDP library that conforms to the public release of JSR 141 (JAIN-SDP) 59 | interfaces. JAIN-SIP RI is a full implementation of RFC 3261. 60 | 61 | {{{http://sip-communicator.org/}SIP Communicator}} is an audio/video Internet phone and instant messenger 62 | that supports some of the most popular instant messaging and telephony protocols such as SIP, Jabber, 63 | AIM/ICQ, MSN, Yahoo! Messenger, Bonjour, IRC, RSS and soon others like IAX.\ 64 | Available under the GNU Lesser General Public License (LGPL). 65 | 66 | * Sponsors 67 | 68 | Thanks to our sponsors: 69 | 70 | * JetBrains for providing a free license of 71 | {{{http://www.jetbrains.com/idea/}IntelliJ Idea}}. 72 | 73 | * {{{http://www.atlassian.com/}Atlassian}} for providing a free license of 74 | the excellent {{{http://www.atlassian.com/software/jira/}JIRA}} Bug tracker 75 | as well as {{{http://www.cenqua.com/clover/}Clover}} and 76 | {{{http://www.cenqua.com/fisheye/}FishEye}}. 77 | 78 | * YourKit {{{http://www.yourkit.com/}Java Profiler}}. 79 | 80 | * Contact 81 | 82 | You can reach me at <<>> at <<>> dot <<>>. 83 | -------------------------------------------------------------------------------- /src/site/apt/patch.apt: -------------------------------------------------------------------------------- 1 | --- 2 | How To Create and Submit a Patch 3 | --- 4 | Stefan Reuter 5 | --- 6 | $Id$ 7 | 8 | How To Create and Submit a Patch 9 | 10 | This documents how to create and submit patches for Asterisk-Java IAX. 11 | 12 | * Introduction 13 | 14 | A patch is exactly what the word says: a small piece of code used to 15 | repair a breach. It is normally a plain text file containing only 16 | the differences between the current version of the code and the 17 | fixed version. 18 | 19 | Often patches are also used to submit enhancements. 20 | 21 | * Generating a Patch 22 | 23 | The preferred way of creating a patch is to create it against latest 24 | SVN. This ensures that the patch works with the latest version of 25 | the source code and makes it easier to apply the patch. 26 | 27 | To generate the patch you need to check out a copy of the source code 28 | from SVN. Look a the {{{cvs-usage.html}CVS Howto}} for 29 | the details. 30 | 31 | After you have made the changes to the source code and 32 | made sure it compiles and works as expected, you can create the 33 | patch file using the command 34 | 35 | +-----------------------------------------+ 36 | svn diff > /path/to/patchfile.patch 37 | +-----------------------------------------+ 38 | 39 | If you do not have access to SVN you can generate the patch against 40 | the latest release. 41 | 42 | To generate the patch you will need two copies of the source code: 43 | one that is unmodified and one containing your changes to the source. 44 | Start by downloading the source code of the latest release, extract 45 | it and make a copy of the entire source directory. After you have 46 | made your changes to one of the source directories and made sure it 47 | compiles and works as expected, you can create the patch file using 48 | the command 49 | 50 | +-----------------------------------------+ 51 | diff -ru /path/to/unmodified/source /path/to/modified/source > /path/to/patchfile.patch 52 | +-----------------------------------------+ 53 | 54 | * Sending a Patch 55 | 56 | The preferred way to submit a patch is via the 57 | {{{http://jira.reucon.com/browse/AJI}Bug Tracker}}. 58 | 59 | The patch can be reviewed there in public and other suggestions 60 | can be discussed. 61 | -------------------------------------------------------------------------------- /src/site/apt/tutorial.apt: -------------------------------------------------------------------------------- 1 | --- 2 | Tutorial 3 | --- 4 | Stefan Reuter 5 | --- 6 | $Id$ 7 | 8 | tbd 9 | -------------------------------------------------------------------------------- /src/site/resources/demo.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | IAX Java Applet Demo Site 6 | 7 | 154 | 155 | 156 | 157 |

Here you can test the IAX Java Applet

158 | 159 |

You will need your own IAX Account to test the applet - i do not provide one for you...

160 | 161 | 173 | 174 |
175 |
176 |
177 | IAX Host:
178 | Calling Number:
179 | Calling Name:
180 | Username:
181 | Secret:
182 |

183 | 184 | Number to dial: 185 |
186 |
187 | 188 | 189 |
190 |
191 |
192 |

Callback functions

193 |
    194 |
  • setup
  • 195 |
    Callback on applet setup - set audio in and out device here
    196 |
  • loaded
  • 197 |
    Called after applet is ready
    198 |
  • registered(status)
  • 199 |
    Gets called on register events (new register, reregister, register failed)
    200 |
  • hostreachable(status, roundtrip)
  • 201 |
    Callback for hostreachable messages (qualify) - does not work for me
    202 |
  • newCall(inbound, far, near, answered, callingname)
  • 203 |
    Callback for a new call setup
    204 |
  • hungUp(causecode)
  • 205 |
    Hangup callback - with the cause code
    206 |
  • ringing(inbound, far, near, answered, callingname)
  • 207 |
    It's ringing - no built in ringer !
    208 |
  • answered(inbound, far, near, answered, callingname)
  • 209 |
    Call got answered
    210 |
211 |
212 |

Exported functions

213 |
    214 |
  • setHost(host)
  • 215 |
    Set the host to connect to with the iax applet
    216 |
  • setCallingNumber(cnumber)
  • 217 |
    do set the calling number to cnumber
    218 |
  • setCallingName(cname)
  • 219 |
    do set the calling name to cname
    220 |
  • setUser(user)
  • 221 |
    do set username which should get used on register
    222 |
  • setPass(pass)
  • 223 |
    do set password which should get used on register
    224 |
  • setWantIncoming(true)
  • 225 |
    WantIncoming=true - register with the server and receive inbound calls
    226 |
  • register()
  • 227 |
    do register with the server
    228 |
  • dial(number)
  • 229 |
    dial the number number
    230 |
  • hangup()
  • 231 |
    Hangup the current call
    232 |
  • setAudioIn(device)
  • 233 |
    Set the audioin device (you have to use the name of the audio device, have to get done in the setup callback)
    234 |
  • setAudioOut(device)
  • 235 |
    Set the audioout device (you have to use the name of the audio device, have to get done in the setup callback)
    236 |
  • getAudioInListLen
  • 237 |
    Returns the length of the audio in list (number of available audio in devices)
    238 |
  • getAudioInList(nr)
  • 239 |
    Returns the devicename of the nr device in the audioin list
    240 |
  • getAudioIn
  • 241 |
    Returns the current choosen audio in device
    242 |
  • getAudioOutListLen
  • 243 |
    Returns the length of the audio out list (number of available audio out devices)
    244 |
  • getAudioOutList(nr)
  • 245 |
    Returns the devicename of the nr device in the audioout list
    246 |
  • getAudioOut
  • 247 |
    Returns the current choosen audio out device
    248 |
249 |
250 | 251 | 252 | -------------------------------------------------------------------------------- /src/site/resources/images/asterisk-java.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asterisk-java/asterisk-java-iax/27b63e2b307262eecba7fe98c62a42def799c2c2/src/site/resources/images/asterisk-java.png -------------------------------------------------------------------------------- /src/site/site.xml: -------------------------------------------------------------------------------- 1 | 2 | 20 | 21 | 22 | 23 | Asterisk-Java-Banner 24 | images/asterisk-java.png 25 | http://asterisk-java.org/ 26 | Asterisk-Java IAX 27 | 28 | 29 | 30 | Sourceforge-Banner 31 | http://sourceforge.net/sflogo.php?group_id=118998&type=5 32 | 33 | 34 | 35 | org.asteriskjava 36 | asterisk-java-skin 37 | 1.0.0 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 63 | 64 | ${reports} 65 | 66 | 67 | -------------------------------------------------------------------------------- /src/test/java/org/asteriskjava/iax/util/MD5DigestTest.java: -------------------------------------------------------------------------------- 1 | package org.asteriskjava.iax.util; 2 | 3 | import junit.framework.TestCase; 4 | 5 | import java.io.UnsupportedEncodingException; 6 | 7 | public class MD5DigestTest extends TestCase { 8 | public void testMd5() throws UnsupportedEncodingException { 9 | MD5Digest digest = new MD5Digest(); 10 | byte[] in = "Hello World".getBytes("UTF-8"); 11 | byte[] out = new byte[digest.getDigestSize()]; 12 | digest.update(in, 0, in.length); 13 | digest.doFinal(out, 0); 14 | } 15 | } 16 | --------------------------------------------------------------------------------