001/* Downsample a stream by the specified amount. 002 003 Copyright (c) 1998-2014 The Regents of the University of California. 004 All rights reserved. 005 Permission is hereby granted, without written agreement and without 006 license or royalty fees, to use, copy, modify, and distribute this 007 software and its documentation for any purpose, provided that the above 008 copyright notice and the following two paragraphs appear in all copies 009 of this software. 010 011 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 012 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 013 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 014 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 015 SUCH DAMAGE. 016 017 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 018 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 019 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 020 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 021 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 022 ENHANCEMENTS, OR MODIFICATIONS. 023 024 PT_COPYRIGHT_VERSION_2 025 COPYRIGHTENDKEY 026 027 */ 028package ptolemy.domains.sdf.lib; 029 030import ptolemy.data.IntToken; 031import ptolemy.data.Token; 032import ptolemy.data.expr.Parameter; 033import ptolemy.kernel.CompositeEntity; 034import ptolemy.kernel.util.Attribute; 035import ptolemy.kernel.util.IllegalActionException; 036import ptolemy.kernel.util.NameDuplicationException; 037 038/////////////////////////////////////////////////////////////////// 039//// DownSample 040 041/** 042 This actor downsamples an input stream by an integer factor by 043 removing tokens. The downsample factor is given by the <i>factor</i> 044 parameter. On each firing, this actor consumes <i>factor</i> tokens from the 045 input and sends only one of them to the output. The one sent 046 depends on the <i>phase</i> parameter. If <i>phase</i> is 0, then 047 the most recent one (the last one consumed) is sent. If <i>phase</i> 048 is 1, then the next most recent one is sent. The value of <i>phase</i> 049 can range up to <i>factor</i>-1, in which case the first one consumed 050 is sent. By default, the <i>factor</i> parameter is 2, 051 so the input sample rate is twice that of the output. 052 The default value for <i>phase</i> is 0. 053 <p> 054 This actor is data polymorphic. It can accept any token 055 type on the input. 056 057 @see UpSample 058 @author Steve Neuendorffer, Edward A. Lee 059 @version $Id$ 060 @since Ptolemy II 1.0 061 @Pt.ProposedRating Yellow (neuendor) 062 @Pt.AcceptedRating Yellow (neuendor) 063 */ 064public class DownSample extends SDFTransformer { 065 /** Construct an actor with the given container and name. 066 * @param container The container. 067 * @param name The name of this actor. 068 * @exception IllegalActionException If the actor cannot be contained 069 * by the proposed container. 070 * @exception NameDuplicationException If the container already has an 071 * actor with this name. 072 */ 073 public DownSample(CompositeEntity container, String name) 074 throws NameDuplicationException, IllegalActionException { 075 super(container, name); 076 077 // Set parameters. 078 factor = new Parameter(this, "factor"); 079 factor.setExpression("2"); 080 081 phase = new Parameter(this, "phase"); 082 phase.setExpression("0"); 083 084 input_tokenConsumptionRate.setExpression("factor"); 085 } 086 087 /////////////////////////////////////////////////////////////////// 088 //// parameters //// 089 090 /** The number of input tokens to read per output token produced. 091 * This is an integer that defaults to 2 and must be greater than 092 * zero. 093 */ 094 public Parameter factor; 095 096 /** The phase of the output with respect to the input. 097 * This is an integer that defaults to 0 and must be between 0 098 * and <i>factor</i>-1. If <i>phase</i> = 0, the most recent 099 * sample is the output, while if <i>phase</i> = <i>factor</i>-1 100 * the oldest sample is the output. 101 */ 102 public Parameter phase; 103 104 /////////////////////////////////////////////////////////////////// 105 //// public methods //// 106 107 /** Ensure that the factor and phase parameters are both positive. 108 * @param attribute The attribute that has changed. 109 * @exception IllegalActionException If the parameters are out of range. 110 */ 111 @Override 112 public void attributeChanged(Attribute attribute) 113 throws IllegalActionException { 114 if (attribute == factor) { 115 int factorValue = ((IntToken) factor.getToken()).intValue(); 116 117 if (factorValue <= 0) { 118 throw new IllegalActionException(this, 119 "Invalid factor: " + factorValue); 120 } 121 } else if (attribute == phase) { 122 int phaseValue = ((IntToken) phase.getToken()).intValue(); 123 124 if (phaseValue < 0) { 125 throw new IllegalActionException(this, 126 "Invalid phase: " + phaseValue); 127 } 128 } else { 129 super.attributeChanged(attribute); 130 } 131 } 132 133 /** Consume <i>factor</i> tokens from the input, and select one of 134 * them to send to the output based on the <i>phase</i>. 135 * @exception IllegalActionException If there is no director, or 136 * if the <i>phase</i> value is out of range. 137 */ 138 @Override 139 public void fire() throws IllegalActionException { 140 super.fire(); 141 142 int factorValue = ((IntToken) factor.getToken()).intValue(); 143 Token[] valueArray = input.get(0, factorValue); 144 145 int phaseValue = ((IntToken) phase.getToken()).intValue(); 146 147 if (phaseValue >= factorValue) { 148 throw new IllegalActionException(this, 149 "Phase is out of range: " + phaseValue); 150 } 151 152 // Send the token. 153 output.send(0, valueArray[factorValue - phaseValue - 1]); 154 } 155}