コード例 #1
0
ファイル: madlld.c プロジェクト: 0xAS/audiowaveform
/****************************************************************************
 * Prints a message on stderr explaining the usage of the program. Two		*
 * versions of this function are provided, depending on the system type.	*
 ****************************************************************************/
static void PrintUsage(void)
{
#ifdef HAVE_GETOPT /* This version is for Unix systems. */
	fprintf(stderr,"usage: %s [-p] [-a <amp/atten>]\n"
			"\t-a\tSets an amplification or attenuation factor expressed\n"
			"\t\tin dB. The factor bounds are [-Inf,%f].\n"
			"\t-p\tRequests that the output samples be filtered as if\n"
			"\t\ttransmitted through a telephone switch.\n",
			ProgName,
			20.*log10(mad_f_todouble(MAD_F_MAX)));
#else /* HAVE_GETOPT */ /* This other version is for non-Unix systems. */
	fprintf(stderr,"usage: %s [<number>] [phone]\n"
			"\t<number> is a floating point number expressing an "
			"amplification\n"
			"\t\tor attenuation factor expressed in dB. The factor bounds\n"
			"\t\tare [-Inf,%f].\n"
			"\tThe \"phone\" argument requests that the output samples be "
			"filtered\n"
			"\t\tas if transmitted through a telephone switch.\n",
			ProgName,
			20.*log10(mad_f_todouble(MAD_F_MAX)));
#endif /* HAVE_GETOPT */
}
コード例 #2
0
ファイル: fixed-back.c プロジェクト: pickerweng/syf-pwm
int main(int argc, char* argv[])
{
	FILE *fp1;
	FILE *fp2;
	FILE *fp3;
	mad_fixed_t X[num_inp], T[num_out], H[num_hid], Y[num_out];
	mad_fixed_t W_xh[num_inp][num_hid], W_hy[num_hid][num_out];
	mad_fixed_t dW_xh[num_inp][num_hid], dW_hy[num_hid][num_out];
	mad_fixed_t Q_h[num_hid], Q_y[num_out];
	mad_fixed_t dQ_h[num_hid], dQ_y[num_out];
	mad_fixed_t delta_h[num_hid], delta_y[num_out];
	mad_fixed_t sum, mse;
	int Icycle, Itrain;
	int i, j, h;

	fp1 = fopen(train_file, "r");
	fp2 = fopen(weight_file, "w");
	fp3 = fopen(mse_file, "w");
	if (fp1 == NULL) {
		puts("File not exist !!");
		getchar();
		exit(1);
	}

	srand((int)time(0));

	for (h = 0; h < num_hid; h++) {
		for (i = 0; i < num_inp; i++) {
			W_xh[i][h] = random_value();
			dW_xh[i][h] = F_ZERO;
		}
	}

	for (j = 0; j <= num_out; j++) {
		for (h = 0; h < num_hid; h++) {
			W_hy[h][j] = random_value();
			dW_hy[h][j] = F_ZERO;
		}
	}

	for (h = 0; h < num_hid; h++) {
		Q_h[h] = F_ZERO;
		dQ_h[h] = F_ZERO;
		delta_h[h] = F_ZERO;
	}

	for (j = 0; j < num_out; j++) {
		Q_y[j] = random_value();
		dQ_y[j] = F_ZERO;
		delta_y[j] = F_ZERO;
	}

	/*start learning */
	float tmp;
	for (Icycle = 0; Icycle < num_cycle; Icycle++) {
		mse = F_ZERO;

		fseek(fp1, 0, 0);
		for (Itrain = 0; Itrain < num_train; Itrain++) {
			for (i = 0; i < num_inp; i++) {
				tmp = parser(fp1);
				X[i] = mad_f_tofixed(tmp);
			}


			for (j = 0; j < num_out; j++) {
				tmp = parser(fp1);
				T[j]= mad_f_tofixed(tmp);
			}

			for (h = 0; h < num_hid; h++) {
				sum = F_ZERO;
				for (i = 0; i < num_inp; i++) {
					sum = mad_f_add(sum, mad_f_mul(X[i], W_xh[i][h]));
				}
				/* H[h] = (float)1.0 / (1.0 + exp(-(sum - Q_h[h]))); */
				tmp = exp(-1.0 * mad_f_todouble(mad_f_sub(sum, Q_h[h])));
				mad_fixed_t exp_result = mad_f_tofixed(tmp);
				H[h] = mad_f_div(F_POS_ONE, mad_f_add(F_POS_ONE, exp_result));
			}

			for (j = 0; j < num_out; j++) {
				sum = F_ZERO;
				for (h = 0; h < num_hid; h++) {
					sum = mad_f_add(sum, mad_f_mul(H[h], W_hy[h][j]));
				}
				/* Y[j] = (float)1.0 / (1.0 + exp(-(sum - Q_y[j]))); */
				tmp = exp(-1.0 * mad_f_todouble(mad_f_sub(sum, Q_y[j])));
				mad_fixed_t exp_result = mad_f_tofixed(tmp);
				Y[j] = mad_f_div(F_POS_ONE, mad_f_add(F_POS_ONE, exp_result));
			}

			for (j = 0; j < num_out; j++) {
				/* delta_y[j] = Y[j] * (1.0 - Y[j]) * (T[j] - Y[j]); */
				mad_fixed_t first, second, third;
				first = Y[j];
				second = mad_f_sub(F_POS_ONE, Y[j]);
				third = mad_f_sub(T[j], Y[j]);
				delta_y[j] = mad_f_mul(mad_f_mul(first, second), third);
			}

			for (h = 0; h < num_hid; h++) {
				sum = F_ZERO;
				for (j = 0; j < num_out; j++) {
					/* sum = sum + W_hy[h][j] * delta_y[j]; */
					sum = mad_f_add(sum, mad_f_mul(W_hy[h][j], delta_y[j]));
				}
				/* delta_h[h] = H[h] * (1.0 - H[h]) * sum; */
				mad_fixed_t first, second, third;
				first = H[h];
				second = mad_f_sub(F_POS_ONE, H[h]);
				third = sum;
				delta_h[h] = mad_f_mul(mad_f_mul(first, second), sum);
			}

			for (j = 0; j < num_out; j++) {
				for (h = 0; h < num_hid; h++) {
					/* dW_hy[h][j] = eta * delta_y[j] * H[h] + alpha * dW_hy[h][j]; */
					mad_fixed_t first, second;
					first = mad_f_mul(mad_f_mul(F_ETA, delta_y[j]), H[h]);
					second = mad_f_mul(F_ALPHA, dW_hy[h][j]);
					dW_hy[h][j] = mad_f_add(first, second);
				}
			}

			for (j = 0; j < num_out; j++) {
				/* dQ_y[j] = -eta * delta_y[j] + alpha * dQ_y[j]; */
				mad_fixed_t first, second;
				first = mad_f_mul(F_NEG_ETA, delta_y[j]);
				second = mad_f_mul(F_ALPHA, dQ_y[j]);
				dQ_y[j] = mad_f_add(first, second);
			}
			for (h = 0; h < num_hid; h++) {
				for (i = 0; i < num_inp; i++) {
					/* dW_xh[i][h] = eta * delta_h[h] * X[i] + alpha * dW_xh[i][h]; */
					mad_fixed_t first, second;
					first = mad_f_mul(X[i], mad_f_mul(F_ETA, delta_h[h]));
					second = mad_f_mul(F_ALPHA, dW_xh[i][h]);
					dW_xh[i][h] = mad_f_add(first, second);
				}
			}

			for (h = 0; h < num_hid; h++) {
				/* dQ_h[h] = -eta * delta_h[h] + alpha * dQ_h[h]; */
				mad_fixed_t first, second;
				first = mad_f_mul(F_NEG_ETA, delta_h[h]);
				second = mad_f_mul(F_ALPHA, dQ_h[h]);
				dQ_h[h] = mad_f_add(first, second);
			}

			for (j = 0; j < num_out; j++) {
				for (h = 0; h < num_hid; h++) {
					/* W_hy[h][j] = W_hy[h][j] + dW_hy[h][j]; */
					tmp = mad_f_todouble(W_hy[h][j]);
					W_hy[h][j] = mad_f_add(W_hy[h][j], dW_hy[h][j]);
				}
			}

			for (j = 0; j < num_out; j++) {
				/* Q_y[j] = Q_y[j] + dQ_y[j]; */
				Q_y[j] = mad_f_add(Q_y[j], dQ_y[j]);
			}

			for (h = 0; h < num_hid; h++) {
				for (i = 0; i < num_inp; i++) {
					/* W_xh[i][h] = W_xh[i][h] + dW_xh[i][h]; */
					W_xh[i][h] = mad_f_add(W_xh[i][h], dW_xh[i][h]);
				}
			}

			for (h = 0; h < num_hid; h++) {
				/* Q_h[h] = Q_h[h] + dQ_h[h]; */
				Q_h[h] = mad_f_add(Q_h[h], dQ_h[h]);
			}

			for (j = 0; j < num_out; j++) {
				/* mse += (T[j] - Y[j]) * (T[j] - Y[j]); */
				mad_fixed_t first, second;
				first = mad_f_sub(T[j], Y[j]);
				second = mad_f_sub(T[j], Y[j]);
				mse = mad_f_add(mse, mad_f_mul(first, second));
			}
		}

		/* mse = mse / num_train; */
		mse = mad_f_div(mse, mad_f_tofixed(num_train));
		if ((Icycle % 10) == 9) {
			printf("\nIcycle=%3d \nmse=%-8.6f\n", Icycle, mad_f_todouble(mse));
			fprintf(fp3,"%3d \n%-8.6f\n", Icycle, mad_f_todouble(mse));
		}
	}

	printf("\n");
	for (h = 0; h < num_hid; h++) {
		for (i = 0; i < num_inp; i++) {
			printf("W_xh[%2d][%2d]=%-8.4f\t", i, h, mad_f_todouble(W_xh[i][h]));
			fprintf(fp2,"%-8.4f\t", mad_f_todouble(W_xh[i][h]));
		}
		printf("\n");
		fprintf(fp2,"\n");
	}
	printf("\n");
	fprintf(fp2,"\n");
	for (j = 0; j < num_out; j++) {
		for (h = 0; h < num_hid; h++) {
			printf("W_hy[%2d][%2d]=%-8.4f\t", h, j, mad_f_todouble(W_hy[h][j]));
			fprintf(fp2,"%-8.4f\t", mad_f_todouble(W_hy[h][j]));
		}
		printf("\n");
		fprintf(fp2,"\n");
	}
	printf("\n");
	fprintf(fp2,"\n");

	for (h = 0; h < num_hid; h++) {
		printf("Q_h[%2d]=%-8.4f\t", h, mad_f_todouble(Q_h[h]));
		fprintf(fp2,"%-8.4f\t", mad_f_todouble(Q_h[h]));
	}
	printf("\n\n");
	fprintf(fp2,"\n\n");
	for (j = 0; j < num_out; j++) {
		printf("Q_y[%2d]=%-8.4f\t", j, mad_f_todouble(Q_y[j]));
		fprintf(fp2,"%-8.4f\t", mad_f_todouble(Q_y[j]));
	}
	printf("\n\n");
	fprintf(fp2,"\n\n");

	fclose(fp1);
	fclose(fp2);
	fclose(fp3);
	return 0;
}
コード例 #3
0
ファイル: mad_plugin.c プロジェクト: azuwis/mpd
static bool
parse_lame(struct lame *lame, struct mad_bitptr *ptr, int *bitlen)
{
	int adj = 0;
	int name;
	int orig;
	int sign;
	int gain;
	int i;

	/* Unlike the xing header, the lame tag has a fixed length.  Fail if
	 * not all 36 bytes (288 bits) are there. */
	if (*bitlen < 288)
		return false;

	for (i = 0; i < 9; i++)
		lame->encoder[i] = (char)mad_bit_read(ptr, 8);
	lame->encoder[9] = '\0';

	*bitlen -= 72;

	/* This is technically incorrect, since the encoder might not be lame.
	 * But there's no other way to determine if this is a lame tag, and we
	 * wouldn't want to go reading a tag that's not there. */
	if (!g_str_has_prefix(lame->encoder, "LAME"))
		return false;

	if (sscanf(lame->encoder+4, "%u.%u",
	           &lame->version.major, &lame->version.minor) != 2)
		return false;

	g_debug("detected LAME version %i.%i (\"%s\")\n",
		lame->version.major, lame->version.minor, lame->encoder);

	/* The reference volume was changed from the 83dB used in the
	 * ReplayGain spec to 89dB in lame 3.95.1.  Bump the gain for older
	 * versions, since everyone else uses 89dB instead of 83dB.
	 * Unfortunately, lame didn't differentiate between 3.95 and 3.95.1, so
	 * it's impossible to make the proper adjustment for 3.95.
	 * Fortunately, 3.95 was only out for about a day before 3.95.1 was
	 * released. -- tmz */
	if (lame->version.major < 3 ||
	    (lame->version.major == 3 && lame->version.minor < 95))
		adj = 6;

	mad_bit_read(ptr, 16);

	lame->peak = mad_f_todouble(mad_bit_read(ptr, 32) << 5); /* peak */
	g_debug("LAME peak found: %f\n", lame->peak);

	lame->track_gain = 0;
	name = mad_bit_read(ptr, 3); /* gain name */
	orig = mad_bit_read(ptr, 3); /* gain originator */
	sign = mad_bit_read(ptr, 1); /* sign bit */
	gain = mad_bit_read(ptr, 9); /* gain*10 */
	if (gain && name == 1 && orig != 0) {
		lame->track_gain = ((sign ? -gain : gain) / 10.0) + adj;
		g_debug("LAME track gain found: %f\n", lame->track_gain);
	}

	/* tmz reports that this isn't currently written by any version of lame
	 * (as of 3.97).  Since we have no way of testing it, don't use it.
	 * Wouldn't want to go blowing someone's ears just because we read it
	 * wrong. :P -- jat */
	lame->album_gain = 0;
#if 0
	name = mad_bit_read(ptr, 3); /* gain name */
	orig = mad_bit_read(ptr, 3); /* gain originator */
	sign = mad_bit_read(ptr, 1); /* sign bit */
	gain = mad_bit_read(ptr, 9); /* gain*10 */
	if (gain && name == 2 && orig != 0) {
		lame->album_gain = ((sign ? -gain : gain) / 10.0) + adj;
		g_debug("LAME album gain found: %f\n", lame->track_gain);
	}
#else
	mad_bit_read(ptr, 16);
#endif

	mad_bit_read(ptr, 16);

	lame->encoder_delay = mad_bit_read(ptr, 12);
	lame->encoder_padding = mad_bit_read(ptr, 12);

	g_debug("encoder delay is %i, encoder padding is %i\n",
	      lame->encoder_delay, lame->encoder_padding);

	mad_bit_read(ptr, 80);

	lame->crc = mad_bit_read(ptr, 16);

	*bitlen -= 216;

	return true;
}
コード例 #4
0
int CDVDAudioCodecLibMad::Decode(BYTE* pData, int iSize)
{
    BYTE* pBuffer = m_inputBuffer;
    //int iBufferSize = iSize;
    bool bFullOutputBuffer = false;

    m_iDecodedDataSize = 0;

    // m_inputBuffer should always have room here for extra bytes
    int iBytesFree = MAD_INPUT_SIZE - m_iInputBufferSize;
    int iBytesUsed = std::min(iSize, iBytesFree);

    // copy data into our buffer for decoding
    memcpy(m_inputBuffer + m_iInputBufferSize, pData, iBytesUsed);
    m_iInputBufferSize += iBytesUsed;

    if (m_bInitialized)
    {
        m_dll.mad_stream_buffer(&m_stream, pBuffer, m_iInputBufferSize);

        while (true)
        {
            if (bFullOutputBuffer || m_dll.mad_frame_decode(&m_frame, &m_stream) != MAD_ERROR_NONE)
            {
                if (m_stream.error == MAD_ERROR_BUFLEN || bFullOutputBuffer)
                {
                    // need more data
                    if (m_stream.next_frame)
                    {
                        // we have some data left, move remaining data to beginning of buffer
                        m_iInputBufferSize = m_stream.bufend - m_stream.next_frame;
                        memmove(m_inputBuffer, m_stream.next_frame, m_iInputBufferSize);
                    }
                    else
                    {
                        m_iInputBufferSize = 0;
                    }

                    return iBytesUsed;
                }

                // sync stream
                if (m_stream.next_frame)
                {
                    m_iInputBufferSize = m_stream.bufend - m_stream.next_frame;
                    pBuffer = (BYTE*)m_stream.next_frame;
                }

                if (m_iInputBufferSize <= 0)
                {
                    return iBytesUsed;
                }

                // buffer again after a sync
                m_dll.mad_stream_buffer(&m_stream, pBuffer, m_iInputBufferSize);
            }
            else
            {
                // decoded some data

                m_iSourceSampleRate = m_frame.header.samplerate;
                m_iSourceChannels   = (m_frame.header.mode == MAD_MODE_SINGLE_CHANNEL) ? 1 : 2;
                m_iSourceBitrate    = m_frame.header.bitrate;
                m_dll.mad_synth_frame(&m_synth, &m_frame);

                {
                    unsigned int nchannels, nsamples;
                    mad_fixed_t const* left_ch, *right_ch;
                    struct mad_pcm* pcm = &m_synth.pcm;
                    float* output = (float*)(m_decodedData + m_iDecodedDataSize);

                    nchannels = pcm->channels;
                    nsamples  = pcm->length;
                    left_ch   = pcm->samples[0];
                    right_ch  = pcm->samples[1];

                    unsigned int iSize = nsamples * sizeof(float) * nchannels;
                    if (iSize < (MAD_DECODED_SIZE - m_iDecodedDataSize))
                    {
                        while (nsamples--)
                        {
                            // output sample(s) in float
                            *output++ = mad_f_todouble(*left_ch++);
                            if (nchannels == 2)
                            {
                                *output++ = mad_f_todouble(*right_ch++);
                            }
                        }
                        m_iDecodedDataSize += iSize;
                    }

                    if (iSize > (MAD_DECODED_SIZE - m_iDecodedDataSize))
                    {
                        // next audio frame is not going to fit
                        bFullOutputBuffer = true;
                    }
                }
            }
        }
    }
    return 0;
}
コード例 #5
0
void CodecMpeg1::process(const QByteArray &data,bool is_last)
{
#ifdef HAVE_LIBMAD
  float pcm[32768*4];
  int frame_offset=0;
  int err_count=0;

  mpeg1_mpeg.append(data);
  mad_stream_buffer(&mpeg1_mad_stream,(const unsigned char *)mpeg1_mpeg.data(),
		    mpeg1_mpeg.length());
  do {
    while(mad_frame_decode(&mpeg1_mad_frame,&mpeg1_mad_stream)==0) {  
      mad_synth_frame(&mpeg1_mad_synth,&mpeg1_mad_frame);
      for(int i=0;i<mpeg1_mad_synth.pcm.length;i++) {
	for(int j=0;j<mpeg1_mad_synth.pcm.channels;j++) {
	  pcm[frame_offset+i*mpeg1_mad_synth.pcm.channels+j]=
	    (float)mad_f_todouble(mpeg1_mad_synth.pcm.samples[j][i]);
	}
      }
      frame_offset+=(mpeg1_mad_synth.pcm.length*mpeg1_mad_synth.pcm.channels);
    }
    if(MAD_RECOVERABLE(mpeg1_mad_stream.error)!=0) {
      if(err_count++>10) {
	Reset();
	break;
      }
    }
  } while(mpeg1_mad_stream.error!=MAD_ERROR_BUFLEN);

  if(mpeg1_mad_stream.error==MAD_ERROR_BUFLEN) {
    if(frame_offset>0) {
      mpeg1_mad_header=mpeg1_mad_frame.header;
      if(!isFramed()) {
	int channels=2;
	if(mpeg1_mad_frame.header.mode==MAD_MODE_SINGLE_CHANNEL) {
	  channels=1;
	}
	setFramed(channels,mpeg1_mad_frame.header.samplerate,
		  mpeg1_mad_frame.header.bitrate/1000);
      }
      else {
	writePcm(pcm,frame_offset/channels(),is_last);
      }
    }
    mpeg1_mpeg=
      mpeg1_mpeg.right(mpeg1_mad_stream.bufend-mpeg1_mad_stream.next_frame);
  }
  if(is_last) {
    frame_offset=0;
    mpeg1_mpeg.append(0,MAD_BUFFER_GUARD);
    mad_stream_buffer(&mpeg1_mad_stream,(const unsigned char *)mpeg1_mpeg.data(),
		      mpeg1_mpeg.length());
    do {
      while(mad_frame_decode(&mpeg1_mad_frame,&mpeg1_mad_stream)==0) {  
	mad_synth_frame(&mpeg1_mad_synth,&mpeg1_mad_frame);
	for(int i=0;i<mpeg1_mad_synth.pcm.length;i++) {
	  for(int j=0;j<mpeg1_mad_synth.pcm.channels;j++) {
	    pcm[frame_offset+i*mpeg1_mad_synth.pcm.channels+j]=
	      (float)mad_f_todouble(mpeg1_mad_synth.pcm.samples[j][i]);
	  }
	}
	frame_offset+=(mpeg1_mad_synth.pcm.length*mpeg1_mad_synth.pcm.channels);
      }
      if(MAD_RECOVERABLE(mpeg1_mad_stream.error)!=0) {
	if(err_count++>10) {
	  Reset();
	  break;
	}
      }
    } while(mpeg1_mad_stream.error!=MAD_ERROR_BUFLEN);
    writePcm(pcm,frame_offset/channels(),is_last);
  }
#endif  // HAVE_LIBMAD
}
コード例 #6
0
uint8_t ADM_AudiocodecMP3::run(uint8_t * inptr, uint32_t nbIn, float *outptr, uint32_t * nbOut)
{
int i;
signed int Sample;
     *nbOut = 0;
     // Shrink ?
     if(ADM_MP3_BUFFER<=_tail+nbIn)
     {
        memmove(_buffer,_buffer+_head,_tail-_head);
        _tail-=_head;
        _head=0;
     }
     ADM_assert(_tail+nbIn<ADM_MP3_BUFFER);
     memcpy(_buffer+_tail,inptr,nbIn);
     _tail+=nbIn;

     // Now feed to libmad
     mad_stream_buffer(Stream, _buffer+_head, _tail-_head);
     while(1)
     {
         Stream->error = MAD_ERROR_NONE;
        if ((i = mad_frame_decode(Frame, Stream)))
        {
            if (MAD_RECOVERABLE(Stream->error))
            {
                    printf(" error :%x \n",(int)Stream->error);
            } else
            {
                if (Stream->error == MAD_ERROR_BUFLEN)	// we consumed everything
                {
                    uint32_t left=0;
                    //printf("Empty,Stream.next_frame : %lx, Stream.bufend :%lx,delta :%ld",
                    //            Stream.next_frame,Stream.bufend,Stream.bufend-Stream.next_frame);  
                    // Update _head
                    if (Stream->next_frame != NULL)
                    {
                        left = Stream->bufend - Stream->next_frame;                        
                    }    
                    ADM_assert(left<=_tail-_head);
                    _head=_tail-left; 
                    return 1;
                 } else
                {
                     fprintf(stderr," unrecoverable frame level error ");
                     return 0;
                }
            }
        }

        mad_synth_frame(Synth, Frame);
	if (MAD_NCHANNELS(&(Frame->header)) == 2) {//Stereo
		for (i = 0; i < Synth->pcm.length; i++) {
			*(outptr++) = (float) mad_f_todouble(Synth->pcm.samples[0][i]);
			*(outptr++) = (float) mad_f_todouble(Synth->pcm.samples[1][i]);
		}
		*nbOut += Synth->pcm.length * 2;
	} else {//Mono
		for (i = 0; i < Synth->pcm.length; i++) {
			*(outptr++) = (float) mad_f_todouble(Synth->pcm.samples[0][i]);
		}
		*nbOut += Synth->pcm.length;
	}
     }

     return 0;
}
コード例 #7
0
ファイル: madlld.c プロジェクト: 0xAS/audiowaveform
/****************************************************************************
 * Command-line arguments parsing. We use two methods and two command-line	*
 * formats depending on the system type. On unix system we apply the good	*
 * old getopt() method, other system are offered a really primitive options	*
 * interface.																*
 ****************************************************************************/
static int ParseArgs(int argc, char * const argv[])
{
	int				DoPhoneFilter=0,
					i;
	double			AmpFactor;
	mad_fixed_t		Amp=MAD_F_ONE;

#ifdef HAVE_GETOPT /* This version is for Unix systems. */
	int				Option;

	/* Parse the command line. */
	while((Option=getopt(argc,argv,"a:p"))!=-1)
		switch(Option)
		{
			/* {5} Set the amplification/attenuation factor, expressed
			 * in dB.
			 */
			case 'a':
				/* If the current linear amplification factor is not
				 * one (MAD_F_ONE) then is was already set. Setting it
				 * again is not permitted.
				 */
				if(Amp!=MAD_F_ONE)
				{
					fprintf(stderr,"%s: the amplification/attenuation factor "
							"was set several times.\n",ProgName);
					return(1);
				}

				/* The decibel value is converted to a linear factor.
				 * That factor is checked against the maximum value
				 * that can be stored in a mad_fixed_t. The upper
				 * bound is MAD_F_MAX, it is converted to a double
				 * value with mad_f_todouble() for comparison.
				 */
				AmpFactor=pow(10.,atof(optarg)/20);
				if(AmpFactor>mad_f_todouble(MAD_F_MAX))
				{
					fprintf(stderr,"%s: amplification out of range.\n",
							ProgName);
					return(1);
				}

				/* Eventually the amplification factor is converted
				 * from double to fixed point with mad_f_tofixed().
				 */
				Amp=mad_f_tofixed(AmpFactor);
				break;

			/* {6} The output is filtered through a telephone wire. */
			case 'p':
				/* Only one occurrence of the option is permitted. */
				if(DoPhoneFilter)
				{
					fprintf(stderr,"%s: the phone-line simulation option "
							"was already set.\n",ProgName);
					return(1);
				}

				/* The output will be filtered through a band-pass
				 * filter simulating a phone line transmission.
				 */
				DoPhoneFilter=1;
				break;

			/* Print usage guide for invalid options. */
			case '?':
			default:
				PrintUsage();
				return(1);
		}
#else /* HAVE_GETOPT */ /* This other version is for non-Unix systems. */
	/* Scan all command-line arguments. */
	for(i=1;i<argc;i++)
	{
		/* Set the amplification factor if the current argument looks
		 * like a number. Look at the comment of the case marked {5}
		 * in the Unix section for details.
		 */
		if(*argv[i]=='+' || *argv[i]=='-' || isdigit(*argv[i]))
		{
			if(Amp!=MAD_F_ONE)
			{
				fprintf(stderr,"%s: the amplification/attenuation factor "
						"was set several times.\n",ProgName);
				return(1);
			}

			AmpFactor=pow(10.,atof(argv[i])/20);
			if(AmpFactor>mad_f_todouble(MAD_F_MAX))
			{
				fprintf(stderr,"%s: amplification out of range.\n",
						ProgName);
				return(1);
			}

			Amp=mad_f_tofixed(AmpFactor);
		}
		else
			/* Use the phone-like filter if the argument is the *
			 * 'phone' string. Look at the comment of the case marked
			 * {6} in the Unix section for details.
			 */
			if(strcmp(argv[i],"phone")==0)
			{
				if(DoPhoneFilter)
				{
					fprintf(stderr,"%s: the phone-line simulation option "
							"was already set.\n",ProgName);
					return(1);
				}
				DoPhoneFilter=1;
			}
			else
			{
				/* The argument is not a recognized one. Print the
				 * usage guidelines and stop there.
				 */
				PrintUsage();
				return(1);
			}
	}
#endif /* HAVE_GETOPT */

	/* Initialize the subband-domain filter coefficients to one if
	 * filtering is requested.
	 */
	if(Amp!=MAD_F_ONE || DoPhoneFilter)
		for(i=0;i<32;i++)
			Filter[i]=MAD_F_ONE;

	/* The amplification/attenuation is applied to the subband-domain
     * filter definition.
	 */
	if(Amp!=MAD_F_ONE)
	{
		DoFilter=1;
		for(i=0;i<32;i++)
			Filter[i]=Amp;
	}

	/* The telephone-like filter is applied to the subband-domain
	 * filter definition. All subbands are set to zero except bands 2
	 * to 6. This programs author has no access to the MPEG audio
	 * specification, he does not know the frequencies bands covered
	 * by the MPEG subbands.
	 */
	if(DoPhoneFilter)
	{
		DoFilter=1;
		Filter[0]=MAD_F(0);
		for(i=5;i<32;i++)
			Filter[i]=MAD_F(0);
	}

	/* Command-line arguments are okay. */
	return(0);
}