/* Copyright (c) 2009-2011 Speech Group at Informatik 5, Univ. Erlangen-Nuremberg, GERMANY Korbinian Riedhammer This file is part of the Java Speech Toolkit (JSTK). The JSTK is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. The JSTK is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the JSTK. If not, see <http://www.gnu.org/licenses/>. */ package de.fau.cs.jstk.sampled; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.ByteOrder; import de.fau.cs.jstk.sampled.filters.BandPassFilter; /** * The (ring) modulation multiplies an input signal (waveform) with a given * carrier frequency. As a result, the input signal spectrum is "lifted" by the * specified frequency and a mirror effect can be observed at the shifting * frequency.<b/> * * In combination with a low-pass filter up to the shifting frequency, a simple * (voice) scrambling can be achieved that can be reversed using the exact same * modulation scheme.<b/> * * The frequency is synthesized as a sinus wave. * * @author sikoried * */ public class RingModulation implements AudioSource { private AudioSource source; /** 2*pi*(freq/samplerate) */ private double fmod; private long ind = 0; /** * Initialize a new SimpleScrambler on the given AudioSource * @param source * @param freq */ public RingModulation(AudioSource source, double freq) { this.source = source; setFrequency(freq); } public void setFrequency(double freq) { this.fmod = 2. * Math.PI * freq / (double) source.getSampleRate(); } public int read(double [] buf) throws IOException { return read(buf, buf.length); } public int read(double [] buf, int length) throws IOException { int r = source.read(buf, length); if (r < 1) return r; /** * The (ring) modulation is a simple multiplication of the waveform with * the carrier frequency. */ for (int i = 0; i < r; ++i) { ind++; buf[i] *= Math.cos(fmod * ind); } return r; } public int getSampleRate() { return source.getSampleRate(); } public boolean getPreEmphasis() { return source.getPreEmphasis(); } public void setPreEmphasis(boolean applyPreEmphasis, double a) { source.setPreEmphasis(applyPreEmphasis, a); } public void tearDown() throws IOException { source.tearDown(); } public static final String SYNOPSIS = "sikoried, 6/8/2011\n" + "(De)Scramble an input ssg/16 signal and write it to stdout. This is a\n" + "ring modulation of the signal with subsequent low-pass at the given scrambling\n" + "frequency.\n\n" + "usage: sampled.RingModulation scrambling-freq < in-ssg8 > out-ssg8"; public static void main(String [] args) throws Exception { if (args.length != 1) { System.err.println(SYNOPSIS); System.exit(1); } // file RawAudioFormat raf = RawAudioFormat.getRawAudioFormat("ssg/16"); AudioFileReader afr = new AudioFileReader(System.in, raf, true); // scrambler double warp = Double.parseDouble(args[0]); RingModulation sc = new RingModulation(afr, Double.parseDouble(args[0])); // low-pass // double [] param = Butterworth.ord(new double [] { 300./4000., cutoff/4000. } , new double [] { 250./4000., (cutoff+200.)/4000. }, 3., 60.); // Butterworth bpf = new Butterworth(sc, 3, 300., warp, true); BandPassFilter bpf = new BandPassFilter(sc, 0., warp, 1024); double scale = Math.pow(2, raf.getBitRate() - 1) - 1; double [] buf = new double [512]; byte [] bbuf = new byte [1024]; int r = 0; while ((r = bpf.read(buf)) > 0) { ByteBuffer bb = ByteBuffer.wrap(bbuf); bb.order(ByteOrder.LITTLE_ENDIAN); int i; for (i = 0; i < r; i++) bb.putShort((short)(buf[i] * scale)); System.out.write(bbuf, 0, r*2); } } }