aspose file tools*
The moose likes Sockets and Internet Protocols and the fly likes Voice Chat Open Source Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Spring in Action this week in the Spring forum!
JavaRanch » Java Forums » Java » Sockets and Internet Protocols
Bookmark "Voice Chat Open Source" Watch "Voice Chat Open Source" New topic
Author

Voice Chat Open Source

omer omran
Greenhorn

Joined: Mar 24, 2004
Posts: 3
Here is the source code of the idea of the voice chat I need some modification to be multi voice chat on the internet
************************************************************************
// read this first
************************************************************************
These programs were written in Java 1.4.1 on Windows XP.
There are two, Sender.java and Receiver.java
Sender.java takes audio input and sends it onto the network.
Receiver.java gets audio input off of the network and plays it.
The sound part of the program does not specify explicitly what mixers should be used,
so it should not be a problem running on other computers.
The network hostname "localhost" is used by the Sending Program. This is set on line 159 of Sender.java,
if you'd need to change it.
The port used is 6001.
To compile, type:
javac *.java
To run, start two terminals and run one in each with no arguments.
ie:
java Sender.java
java Receiver.java
************************************************************************
Receiver.java
************************************************************************

import javax.sound.sampled.*;
import java.io.*;
import java.net.*;
import java.util.*;

public class Receiver extends Thread{
private static final intDEFAULT_INTERNAL_BUFSIZ = 20480; //Audio Buffer Sizes
private static final intDEFAULT_EXTERNAL_BUFSIZ = 20480;
private SourceDataLinem_sourceLine; //Line for Audio Out
private booleanm_bRecording;
private intm_nExternalBufferSize;
static boolean goflag;
static int PacketsIN;

int stepSizeTable[] = { //Step Size Table
7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31, 34,
37, 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143,
157, 173, 190, 209, 230, 253, 279, 307, 337, 371, 408, 449, 494,
544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552,
1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327, 3660, 4026,
4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630, 9493, 10442,
11487, 12635, 13899, 15289, 16818, 18500, 20350, 22385, 24623,
27086, 29794, 32767};

public Receiver(AudioFormat format, int nInternalBufferSize, int nExternalBufferSize, //Sets Up Audio System
String strMixerName)throws LineUnavailableException {
Mixer mixer = null;
if (strMixerName != null){
Mixer.InfomixerInfo = getMixerInfo(strMixerName);
mixer = AudioSystem.getMixer(mixerInfo);
}
DataLine.InfosourceInfo = new DataLine.Info(SourceDataLine.class, format, nInternalBufferSize);
if (mixer != null){
m_sourceLine = (SourceDataLine) mixer.getLine(sourceInfo);
}else{
m_sourceLine = (SourceDataLine) AudioSystem.getLine(sourceInfo);
}
m_sourceLine.open(format, nInternalBufferSize);
m_nExternalBufferSize = nExternalBufferSize;
}

public int getIndexAdjust(float multiplier){ //Returns Index Adjustment according to
int adjust = -1; //the step size multiplier
if(multiplier == 1.75f){
adjust = 8;
}else if(multiplier == 1.5f){
adjust = 6;
}else if(multiplier == 1.25f){
adjust = 4;
}else if(multiplier == 1f){
adjust = 2;
}
return adjust;
}
public float getMultiplier(short Quantization){ //Returns the Step Size Multiplier
if(Quantization == 0){ //According to the 4-bits received per sample
return 0;
}else if(Quantization == 1){
return 0.25f;
}else if(Quantization == 2){
return 0.5f;
}else if(Quantization == 3){
return 0.75f;
}else if(Quantization == 4){
return 1.0f;
}else if(Quantization == 5){
return 1.25f;
}else if(Quantization == 6){
return 1.50f;
}else
return 1.75f;
}

public void start(){ //Starts the Audio Thread
m_sourceLine.start();
super.start(); //Receiving and Decoding
}
public byte[] Decode(byte[] encoded){ //Decoding Method
byte data[] = new byte[322]; //322 byte array to hold decoded samples
short current; //Current Sample being computed
short last; //Previous Sample
short code; //4 bit sample
int index = 0; //Index starts at 0
float stepMult; //Step Size Multiplier
int adjust; //Index Adjustment
int delta; //Sample Delta
int stepSize; //Step Size
int datacount = 2;
boolean sign;
current = encoded[0]; //the first 16-bit sound is turned into a 16-bit short
current = (short)(255 & current);
current = (short)(current << 8);
current = (short)(current | (255 & encoded[1]));
//System.out.println("FIRST CURRENT = "+current);
last = current; //set last to first sample
data[0] = encoded[0];
data[1] = encoded[1];
for(int i = 2; i < encoded.length; i++){ //each cycle should decode 2 16-bit sounds from a byte
sign = false;
datacount = (4*(i-1))-2; //formula for getting the right nodes in the data array from i
code = encoded[i]; //first half of the byte
code = (short)(code & 255);
code = (short)(code >> 4); //shifts left half to right half
code = (short)(code & 15); //assures the left half is 0's
if(code > 7){ //gets the sign of the delta (positive or negative)
sign = true; //if negative, sign = true
code = (short)((byte)code & 7);
}else{
sign = false;
}
stepMult = getMultiplier(code); //Uses the 4-bits to get the Step Size Multiplier
adjust = getIndexAdjust(stepMult); //And the Index Adjustment
stepSize = stepSizeTable[index]; //Uses the index to get the step size
delta = Math.round(stepSize * stepMult);//Sets Delta
if(sign){ delta *= -1; } //Sets Delta to Negative if necessary
current = (short)(last + (short)delta); //Sets Current sample to sum of previous and delta
data[datacount] = (byte)((current >> 8) & 255); //Splits the 16-bit short into two bytes
data[datacount+1] = (byte)(current & 255); //Sets them into the array
index = index + adjust; //Updates the Index
if(index < 0){ index = 0; }
if(index > 88){ index = 88; }
last = current; //Sets Last to Current
//second half of the byte
code = encoded[i]; //Repeats the same thing using the
code = (short)(code & 255); //right half of the byte
code = (short)(code & 15);
if(code > 7){
sign = true;
code = (short)((byte)code & 7);
}else{
sign = false;
}
stepMult = getMultiplier(code);
adjust = getIndexAdjust(stepMult);
stepSize = stepSizeTable[index];
delta = Math.round(stepSize * stepMult);
if(sign){ delta *= -1; }
current = (short)(last + (short)delta);
data[datacount+2] = (byte)((current >> 8) & 255);
data[datacount+3] = (byte)(current & 255);
index = index + adjust;
if(index < 0){ index = 0; }
if(index > 88){ index = 88; }
last = current;
}
return data; //Returns the decompressed data array
}
public void end(){
goflag = false;
}
public void run(){
try{
DatagramSocket serverSocket = new DatagramSocket(6001); //Opens the Receiving Socket
byte[] abBuffer = new byte[82]; //Receiving array
byte[] decoded = new byte[322]; //Decompressed Array
m_bRecording = true;
PacketsIN = 0;
while (m_bRecording & goflag) {
abBuffer = new byte[82];
decoded = new byte[322];
DatagramPacket receivePacket = new DatagramPacket(abBuffer,82); //Creates the Packet
serverSocket.receive(receivePacket); //Fills it from Server
decoded = Decode(receivePacket.getData()); //Decoded the packet's Data
m_sourceLine.write(decoded, 0, decoded.length); //And writes the data to the
PacketsIN++;
} //audio out line
}catch(Exception e){
System.out.println("Receiving Error");
System.exit(1);
}
}
private static Mixer.Info getMixerInfo(String strMixerName){ //Mixer Info for
Mixer.Info[]aInfos = AudioSystem.getMixerInfo(); //Setting up the audio system
for (int i = 0; i < aInfos.length; i++){
if (aInfos[i].getName().equals(strMixerName)){
return aInfos[i];
}
}
return null;
}

public static void main(String[] args) throws Exception {
StringstrMixerName = null;
floatfFrameRate = 8000.0F; //8000 samples per sec
int nInternalBufferSize = DEFAULT_INTERNAL_BUFSIZ; //sets audio buffers
int nExternalBufferSize = DEFAULT_EXTERNAL_BUFSIZ;
goflag = true;
AudioFormataudioFormat = new AudioFormat(fFrameRate, 16, 1, true, true);//sets audio format
//8000 samples per second on Signed PCM and bigEndian format
Receiver audioLoop = null;
long start = System.currentTimeMillis()/1000;
try{
audioLoop = new Receiver(audioFormat, nInternalBufferSize,nExternalBufferSize,//sets the audio system up
strMixerName);
}catch (LineUnavailableException e){
e.printStackTrace();
System.exit(1);
}
audioLoop.start(); //Starts the Receiving Thread, and Decoding and Audio
try{
InputStreamReader input = new InputStreamReader(System.in);
while(input.read() < 0){}
audioLoop.end();
System.out.println("Packets received = "+PacketsIN);
System.out.println("Samples received = "+(PacketsIN*161));
System.out.println("Time Elapsed = "+((System.currentTimeMillis()/1000) - start));
System.out.println("Packets Per Second = "+(PacketsIN / ((System.currentTimeMillis()/1000) - start)));
}catch(IOException e){}
System.exit(1);
}
}

************************************************************************
Sender.java
************************************************************************

import java.io.*;
import javax.sound.sampled.*;
import java.net.*;
import java.util.*;
public class Sender extends Thread{
private static final intDEFAULT_INTERNAL_BUFSIZ = 20480; //Audio Buffer Sizes
private static final intDEFAULT_EXTERNAL_BUFSIZ = 20480;
private TargetDataLinem_targetLine; //Audio In Line
private booleanm_bRecording;
private intm_nExternalBufferSize;
static int PacketsOUT;
static boolean goflag;
int stepSizeTable[] = {
7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31, 34,
37, 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143,
157, 173, 190, 209, 230, 253, 279, 307, 337, 371, 408, 449, 494,
544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552,
1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327, 3660, 4026,
4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630, 9493, 10442,
11487, 12635, 13899, 15289, 16818, 18500, 20350, 22385, 24623,
27086, 29794, 32767};

public Sender(AudioFormat format, int nInternalBufferSize, int nExternalBufferSize, //Gets Lines and Mixers
String strMixerName) throws LineUnavailableException { //Ready

Mixer mixer = null;
if (strMixerName != null){
Mixer.InfomixerInfo = getMixerInfo(strMixerName);
mixer = AudioSystem.getMixer(mixerInfo);
}
DataLine.InfotargetInfo = new DataLine.Info(TargetDataLine.class, format, nInternalBufferSize);
if (mixer != null){
m_targetLine = (TargetDataLine) mixer.getLine(targetInfo);
}else{
m_targetLine = (TargetDataLine) AudioSystem.getLine(targetInfo);
}
m_targetLine.open(format, nInternalBufferSize);
m_nExternalBufferSize = nExternalBufferSize;
}
public int getIndexAdjust(float multiplier){ //Returns the Index Adjustment
int adjust = -1; //According to the step size multiplier
if(multiplier == 1.75f){
adjust = 8;
}else if(multiplier == 1.5f){
adjust = 6;
}else if(multiplier == 1.25f){
adjust = 4;
}else if(multiplier == 1f){
adjust = 2;
}
return adjust;
}
public float[] getMultiplier(int sample, int stepSize){ //returns Step Size Multiplier
int absSample = Math.abs(sample); //AND Quantization Output as a float
float array[] = new float[2]; //it's cast to a byte later
if(absSample < (.25 * stepSize)){
array[0] = 0;
array[1] = 0;
}else if(absSample < (.5 * stepSize)){
array[0] = 0.25f; //returns Multiplier
array[1] = 1; //and Quantization Output
}else if(absSample < (.75 * stepSize)){
array[0] = 0.5f;
array[1] = 2;
}else if(absSample < stepSize){
array[0] = 0.75f;
array[1] = 3;
}else if(absSample < (1.25 * stepSize)){
array[0] = 1f;
array[1] = 4;
}else if(absSample < (1.5 * stepSize)){
array[0] = 1.25f;
array[1] = 5;
}else if(absSample < (1.75 * stepSize)){
array[0] = 1.5f;
array[1] = 6;
}else{
array[0] = 1.75f;
array[1] = 7;
}
return array;
}

public byte[] Encode(byte[] data){ //takes the audio buffer and returns ten encoded packets
byte encoded[] = new byte[82]; //will contain the encoded values
int encodeCount = 2;
int delta;
int stepSize = 0;
float[] stepMult;
short Quant;
int adjust; //index adjustment
int index = 0; //Index starts at 0
short last = 0; //contains the previous 16-bit value (sent value, not original)
short current = 0; //contains the current 16-bit value
byte newbyte = 0;
boolean sign;
encoded[0] = data[0]; //the first 16-bit sound is not encoded
encoded[1] = data[1];
current = data[0]; //the first 16-bit sound is turned into a 16-bit short
current = (short)(255 & current);
current = (short)(current << 8);
current = (short)(current | (255 & data[1]));
last = current;
for(int i = 2; i< data.length; i+=2){ //the next 160 16-bit sounds are encoded into 4-bits
current = 0; //each will share a byte with another sound.
current = data[i];
current = (short)(255 & current);
current = (short)(current << 8);
current = (short)(current | (255 & data[i+1]));
delta = (current - last);
sign = true; //true means greater than 0
if(delta < 0){
sign = false; //false means less than 0, gets appended to Quant
}
delta = Math.abs(delta); //Absolute value of Delta
stepSize = stepSizeTable[index]; //Gets the Step Size
stepMult = getMultiplier(delta,stepSize); //Multiplier
adjust = getIndexAdjust(stepMult[0]); //Index Adjustment
index = index + adjust; //Makes adjustment to index
if(index < 0){ index = 0; }
if(index > 88){ index = 88; }
delta = Math.round(stepSize * stepMult[0]); //Gets the New Delta Value
if(!sign){ delta *= -1; } //Makes it negative if necessary
last = (short)(last +(short)(delta)); //Save value as LAST
Quant = (short)stepMult[1]; //Set Quant as computer Quantization Output
if(!sign){
Quant = (short)((byte)Quant | 8); //Makes 4th bit 1, if negative
}

if((i%4)==2){ //if it's even, shifts to right and stored
encoded[encodeCount] = (byte)((Quant & 255) << 4);
}else{ //if it's odd, OR with the previous value
encoded[encodeCount] = (byte)(encoded[encodeCount] | (255 & Quant));
encodeCount++; //thus, two 4-bit values are stored in one byte
}
}
return encoded; //return ENCODED array
}
public void start(){ //Starts the Audio In Thread
m_targetLine.start();
super.start();
}
public void end(){
goflag = false;
}
public void run() {
try{
byte[] abBuffer = new byte[322]; //buffer size of 161 2-byte samples
byte[] sendData = new byte[82]; //buffer size of 160 4-bit samples and 1 16-bit sample
m_bRecording = true;
DatagramSocket clientSocket = new DatagramSocket();//Starts the Sending Socket
InetAddress IPAddress = InetAddress.getByName("localhost"); //Sets The IP ADDRESS
PacketsOUT = 0;
while (m_bRecording && goflag) {
abBuffer = new byte[322];
sendData = new byte[82];
m_targetLine.read(abBuffer, 0, 322); //Read in the samples
sendData = Encode(abBuffer); //Encode the samples
DatagramPacket sendPacket = new DatagramPacket(sendData,82,IPAddress,6001); //Send the Encoded Samples
clientSocket.send(sendPacket); //161 samples as 82 bytes
PacketsOUT++;
Thread.sleep(20); //Wait 20 milliseconds before sending again

}
clientSocket.close(); //Close Socket
}catch(Exception e){ //Try and Catch required for Thread.sleep()
System.out.println("error");
}
}
private static Mixer.Info getMixerInfo(String strMixerName){ //Returns Mixer info
Mixer.Info[]aInfos = AudioSystem.getMixerInfo(); //Used for setting up the Audio System
for (int i = 0; i < aInfos.length; i++){
if (aInfos[i].getName().equals(strMixerName)){
return aInfos[i];
}
}
return null;
}

public static void main(String[] args){
StringstrMixerName = null;
floatfFrameRate = 8000.0F; //8000 samples per second
int nInternalBufferSize = DEFAULT_INTERNAL_BUFSIZ;
int nExternalBufferSize = DEFAULT_EXTERNAL_BUFSIZ;
AudioFormataudioFormat = new AudioFormat(fFrameRate, 16, 1, true, true);
SenderaudioLoop = null;
goflag = true;
long start = System.currentTimeMillis()/1000;
try{
audioLoop = new Sender(audioFormat, nInternalBufferSize,nExternalBufferSize, //Sets up the Audio System
strMixerName);
}catch (LineUnavailableException e){
e.printStackTrace();
System.exit(1);
}
audioLoop.start(); //Starts the Thread
try{
InputStreamReader input = new InputStreamReader(System.in);
while(input.read() < 0){}
audioLoop.end();
System.out.println("Packets sent = "+PacketsOUT);
System.out.println("Samples sent = "+(PacketsOUT*161));
System.out.println("Time Elapsed = "+((System.currentTimeMillis()/1000) - start));
System.out.println("Packets Per Second = "+(PacketsOUT / ((System.currentTimeMillis()/1000) - start)));

}catch(IOException e){}
System.exit(1);

}

}
Jose Botella
Ranch Hand

Joined: Jul 03, 2001
Posts: 2120
Welcome to the Ranch omer.
Have you considered JMF? Specially because it provides an implementation of the Realtime Transport Protocol. This protocol transmits voice over the net at time
Look at an example here
[ April 23, 2004: Message edited by: Jose Botella ]

SCJP2. Please Indent your code using UBB Code
Vijay Arora
Greenhorn

Joined: May 11, 2004
Posts: 4
Hi omer,
i hv tried to run ur code
but weh i m running Sender.java
it is giving me error msg
"java.io.IOException The handle is invalid."
why it is giving this message?
i hv windows 2000 server and JDK 1.4
plz help me out. This code is very usefull 4 me.
thanx in advance.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Voice Chat Open Source