/*
* festivoice
*
* Copyright 2009 FURUHASHI Sadayuki, KASHIHARA Shuzo, SHIBATA Yasuharu
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.festivoice;
import java.util.*;
import java.lang.*;
import java.net.*;
import java.util.concurrent.*;
import javax.sound.sampled.*;
import org.xiph.speex.SpeexEncoder;
public class ThreadedPacketSender extends Thread
{
private BlockingQueue<byte[]> queue;
private SessionInfo sessionInfo;
private StreamSender.CodecInfo codecInfo;
private SpeexEncoder encoder;
private int baseByteArraySize;
private boolean endFlag = false;
public static class SessionInfo
{
private InetSocketAddress serverAddress;
private DatagramSocket socket;
private String channelName;
private String userName;
public SessionInfo(InetSocketAddress serverAddress, DatagramSocket socket, String channelName, String userName)
{
this.serverAddress = serverAddress;
this.socket = socket;
this.channelName = channelName;
this.userName = userName;
}
}
public ThreadedPacketSender(SessionInfo sessionInfo, StreamSender.CodecInfo codecInfo, BlockingQueue<byte[]> queue)
{
this.sessionInfo = sessionInfo;
this.codecInfo = codecInfo;
this.queue = queue;
// Initialize Speex Encoder
encoder = new SpeexEncoder();
encoder.init(codecInfo.mode, codecInfo.quality, (int)codecInfo.format.getSampleRate(), codecInfo.format.getChannels(), codecInfo.vbr);
// 内部では、byteからfloatに変換しているため、2倍する必要がある
baseByteArraySize = encoder.getFrameSize() * encoder.getChannels() * 2;
}
public int getBaseArraySize()
{
return baseByteArraySize;
}
public void end()
{
endFlag = true;
}
public void run()
{
try {
while(!endFlag) {
byte[] soundBuffer = queue.take();
if(soundBuffer.length != 0) {
// Encode voice data
encoder.processData(soundBuffer, 0, baseByteArraySize);
for (int i = 1; i < codecInfo.countFrames; i++) {
encoder.processData(soundBuffer, baseByteArraySize * i, baseByteArraySize);
}
byte[] encodedData = new byte[encoder.getProcessedDataByteSize()];
encoder.getProcessedData(encodedData, 0);
soundBuffer = encodedData;
}
byte[] buffer = UDPData.serialize(sessionInfo.userName, sessionInfo.channelName, soundBuffer, 0, (short)0);
DatagramPacket packet = new DatagramPacket(buffer, buffer.length, sessionInfo.serverAddress);
sessionInfo.socket.send(packet);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}