annotate src/samer/audio/FileSink.java @ 8:5e3cbbf173aa tip

Reorganise some more
author samer
date Fri, 05 Apr 2019 22:41:58 +0100
parents bf79fb79ee13
children
rev   line source
samer@0 1 /*
samer@0 2 * FileSink.java
samer@0 3 *
samer@0 4 * Copyright (c) 2000, Samer Abdallah, King's College London.
samer@0 5 * All rights reserved.
samer@0 6 *
samer@0 7 * This software is provided AS iS and WITHOUT ANY WARRANTY;
samer@0 8 * without even the implied warranty of MERCHANTABILITY or
samer@0 9 * FITNESS FOR A PARTICULAR PURPOSE.
samer@0 10 */
samer@0 11
samer@0 12 package samer.audio;
samer@0 13
samer@0 14 import samer.core.*;
samer@0 15 import samer.core.types.*;
samer@0 16 import samer.core.util.*;
samer@0 17 import samer.tools.*;
samer@0 18 import javax.sound.sampled.*;
samer@0 19 import java.io.*;
samer@0 20
samer@0 21 import org.tritonus.share.sampled.AudioSystemShadow;
samer@0 22 import org.tritonus.share.sampled.file.AudioOutputStream;
samer@0 23
samer@0 24 /**
samer@0 25 An AudioSink that writes to a wav file.
samer@0 26 Viewable name: "wavewriter"<br>
samer@0 27 Properties read from current environment:
samer@0 28 <dl>
samer@0 29 <dt>filesink.current
samer@0 30 <dd>Current file (String)
samer@0 31 <dt>filesink.scale
samer@0 32 <dd>scale factor for converting floats/doubles (Double)
samer@0 33 </dl>
samer@0 34 */
samer@0 35
samer@0 36 public class FileSink extends Viewable implements AudioSink, Agent
samer@0 37 {
samer@0 38 VFile file;
samer@0 39 AudioOutputStream out=null;
samer@0 40 AudioFormat format;
samer@0 41 VDouble scale;
samer@0 42
samer@0 43 public FileSink(String filename, AudioFormat fmt) throws Exception {
samer@0 44 this(fmt); file.setFile(new File(filename));
samer@0 45 }
samer@0 46
samer@0 47 public FileSink(AudioFormat fmt)
samer@0 48 {
samer@0 49 super("filessink");
samer@0 50
samer@0 51 Shell.push(node);
samer@0 52 file=new VFile("file","",0);
samer@0 53 scale=new VDouble("scale",1.0,0);
samer@0 54 Shell.push("audio");
samer@0 55 format=fmt;
samer@0 56 Shell.pop();
samer@0 57 Shell.pop();
samer@0 58
samer@0 59 setAgent(this);
samer@0 60 Shell.registerViewable(this);
samer@0 61 }
samer@0 62
samer@0 63 public void dispose() {
samer@0 64 close();
samer@0 65 Shell.deregisterViewable(this);
samer@0 66 file.dispose();
samer@0 67 }
samer@0 68
samer@0 69 public VDouble getScale() { return scale; }
samer@0 70 public void setFormat(AudioFormat f) { format=f; }
samer@0 71
samer@0 72 public boolean isOpen() { return out!=null; }
samer@0 73 public void open() throws Exception { open(file.getFile()); }
samer@0 74 public synchronized void open(File file) throws Exception
samer@0 75 {
samer@0 76 Shell.trace("wave writer opening "+file+" as "+format);
samer@0 77
samer@0 78 out=AudioSystemShadow.getAudioOutputStream(
samer@0 79 AudioFileFormat.Type.WAVE,format,AudioSystem.NOT_SPECIFIED,
samer@0 80 new BufferedOutputStream(
samer@0 81 new FileOutputStream(file)));
samer@0 82 this.file.setFile(file);
samer@0 83 }
samer@0 84
samer@0 85 public synchronized void close() {
samer@0 86 try { if (out!=null) out.close(); out=null; }
samer@0 87 catch (IOException ex) { Shell.trace("*** Error closing: "+ex); }
samer@0 88 }
samer@0 89
samer@0 90 public Task writer(final double [] dbuf, final int off, final int len) {
samer@0 91 return new AnonymousTask() {
samer@0 92 byte [] bbuf = new byte[2*len];
samer@0 93
samer@0 94 public void write(double dbuf[], int off, int len) throws Exception {
samer@0 95 synchronized (FileSink.this) {
samer@0 96 Util.doubleToShort(dbuf,bbuf,off,len,scale.value);
samer@0 97 writeBytes(bbuf, 2*len);
samer@0 98 }
samer@0 99 }
samer@0 100 public void run() throws Exception {
samer@0 101 synchronized (FileSink.this) {
samer@0 102 Util.doubleToShort(dbuf,bbuf,off,len,scale.value);
samer@0 103 writeBytes(bbuf, bbuf.length);
samer@0 104 }
samer@0 105 }
samer@0 106 };
samer@0 107 }
samer@0 108
samer@0 109 public Task writer(final float [] dbuf, final int off, final int len) {
samer@0 110 return new AnonymousTask() {
samer@0 111 byte [] bbuf = new byte[2*len];
samer@0 112
samer@0 113 public void write(float dbuf[], int off, int len) throws Exception {
samer@0 114 synchronized (FileSink.this) {
samer@0 115 Util.floatToShort(dbuf,bbuf,off,len,(float)scale.value);
samer@0 116 writeBytes(bbuf, 2*len);
samer@0 117 }
samer@0 118 }
samer@0 119 public void run() throws Exception {
samer@0 120 synchronized (FileSink.this) {
samer@0 121 Util.floatToShort(dbuf,bbuf,off,len,(float)scale.value);
samer@0 122 writeBytes(bbuf, bbuf.length);
samer@0 123 }
samer@0 124 }
samer@0 125 };
samer@0 126 }
samer@0 127
samer@0 128 private void writeBytes(byte [] buf,int len) throws Exception {
samer@0 129 int count = out.write(buf, 0, len);
samer@0 130 for (int n=count; n<len; n+=count) {
samer@0 131 count = out.write(buf, n, len - n);
samer@0 132 if (count<=0) throw new Exception("Write failed");
samer@0 133 }
samer@0 134 }
samer@0 135
samer@0 136 public void getCommands(Agent.Registry r) { r.add("open").add("close").add("set scale"); }
samer@0 137 public void execute(String cmd, Environment env) throws Exception {
samer@0 138 if (cmd.equals("open")) {close(); open(); }
samer@0 139 else if (cmd.equals("close")) close();
samer@0 140 else if (cmd.equals("set scale")) { env.datum().get(scale); }
samer@0 141 }
samer@0 142
samer@0 143 // Viewable
samer@0 144 public Viewer getViewer() {
samer@0 145 DefaultViewer vwr=new DefaultViewer(this);
samer@0 146 vwr.add(file);
samer@0 147 vwr.add(Shell.createButtonsFor(this));
samer@0 148 return vwr;
samer@0 149 }
samer@0 150 }