Example #1
0
//////////////////////////////////////////////////////////////////////
// Init - initialized or reiniyialized encoder SDK with given input 
// and output settings
//////////////////////////////////////////////////////////////////////
HRESULT CEncoder::Init()
{
    CAutoLock l(&m_lock);

    m_outOffset     = 0;
    m_outReadOffset = 0;

    m_bFinished     = FALSE;

    m_frameCount    = 0;

    if (!pgf)
    {
        if (!m_bInpuTypeSet || !m_bOutpuTypeSet)
            return E_UNEXPECTED;

        // Init Lame library
        // note: newer, safer interface which doesn't 
        // allow or require direct access to 'gf' struct is being written
        // see the file 'API' included with LAME.
        if (pgf = lame_init())
        {
            lame_set_num_channels(pgf, m_wfex.nChannels);
            lame_set_in_samplerate(pgf, m_wfex.nSamplesPerSec);
            lame_set_out_samplerate(pgf, m_mabsi.dwSampleRate);
            if ((lame_get_out_samplerate(pgf) >= 32000) && (m_mabsi.dwBitrate < 32))
                lame_set_brate(pgf, 32);
            else
                lame_set_brate(pgf, m_mabsi.dwBitrate);
            lame_set_VBR(pgf, m_mabsi.vmVariable);
            lame_set_VBR_min_bitrate_kbps(pgf, m_mabsi.dwVariableMin);
            lame_set_VBR_max_bitrate_kbps(pgf, m_mabsi.dwVariableMax);

            lame_set_copyright(pgf, m_mabsi.bCopyright);
            lame_set_original(pgf, m_mabsi.bOriginal);
            lame_set_error_protection(pgf, m_mabsi.bCRCProtect);

            lame_set_bWriteVbrTag(pgf, m_mabsi.dwXingTag);
            lame_set_strict_ISO(pgf, m_mabsi.dwStrictISO);
            lame_set_VBR_hard_min(pgf, m_mabsi.dwEnforceVBRmin);

            if (lame_get_num_channels(pgf) == 2 && !m_mabsi.bForceMono)
            {
                //int act_br = pgf->VBR ? pgf->VBR_min_bitrate_kbps + pgf->VBR_max_bitrate_kbps / 2 : pgf->brate;

                // Disabled. It's for user's consideration now
                //int rel = pgf->out_samplerate / (act_br + 1);
                //pgf->mode = rel < 200 ? m_mabsi.ChMode : JOINT_STEREO;

                lame_set_mode(pgf, m_mabsi.ChMode);
            }
            else
                lame_set_mode(pgf, MONO);

            if (lame_get_mode(pgf) == JOINT_STEREO)
                lame_set_force_ms(pgf, m_mabsi.dwForceMS);
            else
                lame_set_force_ms(pgf, 0);

//            pgf->mode_fixed = m_mabsi.dwModeFixed;

            if (m_mabsi.dwVoiceMode != 0)
            {
                lame_set_lowpassfreq(pgf,12000);
                ///pgf->VBR_max_bitrate_kbps = 160;
            }

            if (m_mabsi.dwKeepAllFreq != 0)
            {
                ///pgf->lowpassfreq = -1;
                ///pgf->highpassfreq = -1;
                /// not available anymore
            }

            lame_set_quality(pgf, m_mabsi.dwQuality);
            lame_set_VBR_q(pgf, m_mabsi.dwVBRq);

            lame_init_params(pgf);

            // encoder delay compensation
            {
                int const nch = lame_get_num_channels(pgf);
                short * start_padd = (short *)calloc(48, nch * sizeof(short));

				int out_bytes = 0;

                if (nch == 2)
                    out_bytes = lame_encode_buffer_interleaved(pgf, start_padd, 48, m_outFrameBuf, OUT_BUFFER_SIZE);
                else
                    out_bytes = lame_encode_buffer(pgf, start_padd, start_padd, 48, m_outFrameBuf, OUT_BUFFER_SIZE);

				if (out_bytes > 0)
					m_outOffset += out_bytes;

                free(start_padd);
            }

            return S_OK;
        }

        return E_FAIL;
    }

    return S_OK;
}
Example #2
0
//////////////////////////////////////////////////////////////////////
// Encode - encodes data placed on pdata and returns
// the number of processed bytes
//////////////////////////////////////////////////////////////////////
int CEncoder::Encode(const short * pdata, int data_size)
{
    CAutoLock l(&m_lock);

    if (!pgf || !m_outFrameBuf || !pdata || data_size < 0 || (data_size & (sizeof(short) - 1)))
        return -1;

    // some data left in the buffer, shift to start
    if (m_outReadOffset > 0)
    {
        if (m_outOffset > m_outReadOffset)
            memmove(m_outFrameBuf, m_outFrameBuf + m_outReadOffset, m_outOffset - m_outReadOffset);

        m_outOffset -= m_outReadOffset;
    }

    m_outReadOffset = 0;



    m_bFinished = FALSE;

    int bytes_processed = 0;
    int const nch = lame_get_num_channels(pgf);

    while (1)
    {
        int nsamples = (data_size - bytes_processed) / (sizeof(short) * nch);

        if (nsamples <= 0)
            break;

        if (nsamples > 1152)
            nsamples = 1152;

        if (m_outOffset >= OUT_BUFFER_MAX)
            break;

        int out_bytes = 0;

        if (nch == 2)
            out_bytes = lame_encode_buffer_interleaved(
                                            pgf,
                                            (short *)(pdata + (bytes_processed / sizeof(short))),
                                            nsamples,
                                            m_outFrameBuf + m_outOffset,
                                            OUT_BUFFER_SIZE - m_outOffset);
        else
            out_bytes = lame_encode_buffer(
                                            pgf,
                                            pdata + (bytes_processed / sizeof(short)),
                                            pdata + (bytes_processed / sizeof(short)),
                                            nsamples,
                                            m_outFrameBuf + m_outOffset,
                                            OUT_BUFFER_SIZE - m_outOffset);

        if (out_bytes < 0)
            return -1;

        m_outOffset     += out_bytes;
        bytes_processed += nsamples * nch * sizeof(short);
    }

    return bytes_processed;
}
Example #3
0
/*------------------------------------------------------------------------------
 *  Write data to the encoder
 *----------------------------------------------------------------------------*/
unsigned int
LameLibEncoder :: write (   const void    * buf,
                            unsigned int    len )           throw ( Exception )
{
    if ( !isOpen() ) {
        return 0;
    }

    unsigned int    bitsPerSample = getInBitsPerSample();
    unsigned int    channels      = getInChannel();

    if ( channels != 1 && channels != 2 ) {
        throw Exception( __FILE__, __LINE__,
                         "unsupported number of channels for the encoder",
                         channels );
    }
 
    unsigned int    sampleSize = (bitsPerSample / 8) * channels;
    unsigned char * b = (unsigned char*) buf;
    unsigned int    processed = len - (len % sampleSize);
    unsigned int    nSamples = processed / sampleSize;
    short int       leftBuffer[nSamples];
    short int       rightBuffer[nSamples];

    if ( bitsPerSample == 8 ) {
        conv8( b, processed, leftBuffer, rightBuffer, channels);
    } else if ( bitsPerSample == 16 ) {
        conv16( b, processed, leftBuffer, rightBuffer, channels);
    } else {
        throw Exception( __FILE__, __LINE__,
                        "unsupported number of bits per sample for the encoder",
                         bitsPerSample );
    }

    // data chunk size estimate according to lame documentation
    unsigned int    mp3Size = (unsigned int) (1.25 * nSamples + 7200);
    unsigned char   mp3Buf[mp3Size];
    int             ret;

    ret = lame_encode_buffer( lameGlobalFlags,
                              leftBuffer,
                              channels == 2 ? rightBuffer : leftBuffer,
                              nSamples,
                              mp3Buf,
                              mp3Size );
    
    if ( ret < 0 ) {
        reportEvent( 3, "lame encoding error", ret);
        return 0;
    }

    unsigned int    written = sink->write( mp3Buf, ret);
    // just let go data that could not be written
    if ( written < (unsigned int) ret ) {
        reportEvent( 2,
                     "couldn't write all from encoder to underlying sink",
                     ret - written);
    }

    return processed;
}
Example #4
0
/*------------------------------------------------------------------------------
 *  Write data to the encoder
 *----------------------------------------------------------------------------*/
unsigned int
LameLibEncoder :: write (   const void    * buf,
                            unsigned int    len )           throw ( Exception )
{
    if ( !isOpen() ) {
        return 0;
    }

    unsigned int    bitsPerSample = getInBitsPerSample();
    unsigned int    inChannels    = getInChannel();

    unsigned int    sampleSize = (bitsPerSample / 8) * inChannels;
    unsigned char * b = (unsigned char*) buf;
    unsigned int    processed = len - (len % sampleSize);
    unsigned int    nSamples = processed / sampleSize;
    short int     * leftBuffer  = new short int[nSamples];
    short int     * rightBuffer = new short int[nSamples];

    if ( bitsPerSample == 8 ) {
        Util::conv8( b, processed, leftBuffer, rightBuffer, inChannels);
    } else if ( bitsPerSample == 16 ) {
        Util::conv16( b,
                      processed,
                      leftBuffer,
                      rightBuffer,
                      inChannels,
                      isInBigEndian());
    } else {
        delete[] leftBuffer;
        delete[] rightBuffer;
        throw Exception( __FILE__, __LINE__,
                        "unsupported number of bits per sample for the encoder",
                         bitsPerSample );
    }

    // data chunk size estimate according to lame documentation
    // NOTE: mp3Size is calculated based on the number of input channels
    //       which may be bigger than need, as output channels can be less
    unsigned int    mp3Size = (unsigned int) (1.25 * nSamples + 7200);
    unsigned char * mp3Buf  = new unsigned char[mp3Size];
    int             ret;

    ret = lame_encode_buffer( lameGlobalFlags,
                              leftBuffer,
                              inChannels == 2 ? rightBuffer : leftBuffer,
                              nSamples,
                              mp3Buf,
                              mp3Size );

    delete[] leftBuffer;
    delete[] rightBuffer;

    if ( ret < 0 ) {
        reportEvent( 3, "lame encoding error", ret);
        delete[] mp3Buf;
        return 0;
    }

    unsigned int    written = sink->write( mp3Buf, ret);
    delete[] mp3Buf;
    // just let go data that could not be written
    if ( written < (unsigned int) ret ) {
        reportEvent( 2,
                     "couldn't write all from encoder to underlying sink",
                     ret - written);
    }

    return processed;
}
static switch_status_t shout_file_write(switch_file_handle_t *handle, void *data, size_t *len)
{
	shout_context_t *context;
	int rlen = 0;
	int16_t *audio = data;
	size_t nsamples = *len;

	if (!handle) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error no handle\n");
		return SWITCH_STATUS_FALSE;
	}

	if (!(context = handle->private_info)) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error no context\n");
		return SWITCH_STATUS_FALSE;
	}

	if (context->err) {
		return SWITCH_STATUS_FALSE;
	}

	if (context->shout && !context->shout_init) {

		if (!context->gfp) {
			return SWITCH_STATUS_FALSE;
		}

		context->shout_init++;
		if (shout_open(context->shout) != SHOUTERR_SUCCESS) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error opening stream: %s\n", shout_get_error(context->shout));
			context->err++;
			return SWITCH_STATUS_FALSE;
		}
		launch_write_stream_thread(context);
	}

	if (handle->handler && context->audio_mutex) {
		switch_mutex_lock(context->audio_mutex);
		if (context->audio_buffer) {
			if (!switch_buffer_write(context->audio_buffer, data, (nsamples * sizeof(int16_t) * handle->channels))) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Buffer error\n");
				context->err++;
			}
		} else {
			context->err++;
		}

		switch_mutex_unlock(context->audio_mutex);
		if (context->err) {
			return SWITCH_STATUS_FALSE;
		}

		handle->sample_count += *len;
		return SWITCH_STATUS_SUCCESS;
	}

	if (!context->lame_ready) {
		lame_init_params(context->gfp);
		lame_print_config(context->gfp);
		context->lame_ready = 1;
	}

	if (context->mp3buflen < nsamples * 4) {
		context->mp3buflen = nsamples * 4;
		context->mp3buf = switch_core_alloc(context->memory_pool, context->mp3buflen);
	}

	if (handle->channels == 2) {
		switch_size_t i, j = 0;

		if (context->llen < nsamples) {
			context->l = switch_core_alloc(context->memory_pool, nsamples * 2);
			context->r = switch_core_alloc(context->memory_pool, nsamples * 2);
			context->llen = context->rlen = nsamples;
		}

		for (i = 0; i < nsamples; i++) {
			context->l[i] = audio[j++];
			context->r[i] = audio[j++];
		}

		if ((rlen = lame_encode_buffer(context->gfp, context->l, context->r, nsamples, context->mp3buf, context->mp3buflen)) < 0) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "MP3 encode error %d!\n", rlen);
			return SWITCH_STATUS_FALSE;
		}

	} else if (handle->channels == 1) {
		if ((rlen = lame_encode_buffer(context->gfp, audio, NULL, nsamples, context->mp3buf, context->mp3buflen)) < 0) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "MP3 encode error %d!\n", rlen);
			return SWITCH_STATUS_FALSE;
		}
	} else {
		rlen = 0;
	}

	if (rlen) {
		int ret = fwrite(context->mp3buf, 1, rlen, context->fp);
		if (ret < 0) {
			return SWITCH_STATUS_FALSE;
		}
	}

	handle->sample_count += *len;

	return SWITCH_STATUS_SUCCESS;
}
//core function to encide WAV to MP3, relying on LAME library
void encode(char* wavFilePath, char* mp3FilePath) {

	FILE* wavFile = fopen(wavFilePath, "rb");
	FILE* mp3File = fopen(mp3FilePath, "wb+");
	int readPCMSampleCount;
	
	short int pcmBuffer[PCM_BUF_SIZE];
	unsigned char mp3Buffer[MP3_BUF_SIZE];

	unsigned short channel;
	unsigned long sampleRate;
	unsigned short blockAlign;

	lame_t lame = lame_init();

	if((wavFile == NULL) || (mp3File == NULL)) {
		printErrorMessage(FILE_IO_EXCEPTION);
		return;
	}
	
	if(lame == NULL) {
		printErrorMessage(LAME_API_ERROR);
		return;
	}

	//Set number of channels
	else if(fseek(wavFile, 22, SEEK_SET) != 0) {
		printErrorMessage(FILE_IO_EXCEPTION);
		return;
	}
	else if(fread(&channel, 2, 1, wavFile) < 1) {
		printErrorMessage(FILE_IO_EXCEPTION);
		return;
	}
	else {
		lame_set_num_channels(lame, channel);
		lame_set_mode(lame, (channel == 1) ? MONO : JOINT_STEREO);
	}

	//Set number of sample rate
	if(fseek(wavFile, 24, SEEK_SET) != 0) {
		printErrorMessage(FILE_IO_EXCEPTION);
		return;
	}
	else if(fread(&sampleRate, 4, 1, wavFile) < 1) {
		printErrorMessage(FILE_IO_EXCEPTION);
		return;
	}
	else {
		lame_set_in_samplerate(lame, sampleRate);
		lame_set_out_samplerate(lame, sampleRate);
	}
	
	//Set block align (byte/sample)
	if(fseek(wavFile, 32, SEEK_SET) != 0) {
		printErrorMessage(FILE_IO_EXCEPTION);
		return;
	}
	else if(fread(&blockAlign, 4, 1, wavFile) < 1) {
		printErrorMessage(FILE_IO_EXCEPTION);
		return;
	}

	//Look for data chank in the WAV file
	if(fseek(wavFile, 36, SEEK_SET) != 0) {
		printErrorMessage(FILE_IO_EXCEPTION);
		return;
	}
	else {
		char data[5];
		data[4] = '\0';
		
		while(fread(data, 4, 1, wavFile) == 1) {
			
			if(strcmp(data, "data") != 0) {
				//Search data chank by 1 byte
				fseek(wavFile, -3, SEEK_CUR);
				continue;
			}
			else if(fseek(wavFile, 4, SEEK_CUR)) {
				//data chank was found, then skip next 4 byte(indicating data size) to proceed
				printErrorMessage(FILE_IO_EXCEPTION);
				return;
			}
			else {
				//Now we are pointing the head of the PCM data, let's proceed
				break;
			}
		}
		
		//If data chank cannot be detected
		if(feof(wavFile)) {
			printErrorMessage(NOT_WAV_HEADER);
			return;
		}
	}
	
	
	//Encoding conficuration with "good" level quality
	lame_set_quality(lame, 5);
	lame_set_VBR(lame, vbr_default);
	lame_set_VBR_q(lame, 5);

	if(lame_init_params(lame) == -1) {
		printErrorMessage(LAME_API_ERROR);
		return;
	}
	
	//Perfoem encoding
	do {
		int encodedSampleCount;

		readPCMSampleCount = fread(pcmBuffer, blockAlign, PCM_BUF_SIZE / blockAlign, wavFile);
		
		if(readPCMSampleCount != 0) {

			if(channel == 1) { //For monoral case
				
				short int pcmBufferRight[PCM_BUF_SIZE];
				short int pcmBufferLeft[PCM_BUF_SIZE];
				int i;
				
				for(i = 0; i < PCM_BUF_SIZE; i++) {
					pcmBufferRight[i] = pcmBuffer[i];
					pcmBufferLeft[i] = pcmBuffer[i];
				}
				encodedSampleCount = lame_encode_buffer(lame, pcmBufferLeft, pcmBufferRight, readPCMSampleCount, mp3Buffer, MP3_BUF_SIZE);
			}
			
			else { //For stereo case
				encodedSampleCount = lame_encode_buffer_interleaved(lame, pcmBuffer, readPCMSampleCount, mp3Buffer, MP3_BUF_SIZE);
			}
		}
		else {
			encodedSampleCount = lame_encode_flush(lame, mp3Buffer, MP3_BUF_SIZE);
		}
		
		if(encodedSampleCount < 0) {
			printErrorMessage(LAME_API_ERROR);
		}
		else {
			fwrite(mp3Buffer, encodedSampleCount, 1, mp3File);
		}
		
	} while(readPCMSampleCount != 0);
	
	lame_close(lame);

	fclose(wavFile);
	fclose(mp3File);
}
static inline void free_context(shout_context_t *context)
{
	int ret;

	if (context) {
		switch_mutex_lock(context->audio_mutex);
		context->err++;
		switch_mutex_unlock(context->audio_mutex);

		if (context->stream_url) {
			int sanity = 0;

			while (context->thread_running) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Waiting for stream to terminate: %s\n", context->stream_url);
				switch_yield(500000);
				if (++sanity > 10) {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Giving up waiting for stream to terminate: %s\n", context->stream_url);
					break;
				}
			}
		}

		switch_thread_rwlock_wrlock(context->rwlock);

		if (context->mh) {
			mpg123_close(context->mh);
			mpg123_delete(context->mh);
		}

		if (context->fp) {
			unsigned char mp3buffer[20480];
			int len;
			int16_t blank[2048] = { 0 }, *r = NULL;


			if (context->channels == 2) {
				r = blank;
			}

			len = lame_encode_buffer(context->gfp, blank, r, sizeof(blank) / 2, mp3buffer, sizeof(mp3buffer));

			if (len) {
				ret = fwrite(mp3buffer, 1, len, context->fp);
			}

			while ((len = lame_encode_flush(context->gfp, mp3buffer, sizeof(mp3buffer))) > 0) {
				ret = fwrite(mp3buffer, 1, len, context->fp);
				if (ret < 0) {
					break;
				}
			}

			lame_mp3_tags_fid(context->gfp, context->fp);

			fclose(context->fp);
			context->fp = NULL;
		}

		if (context->shout) {
			if (context->gfp) {
				unsigned char mp3buffer[8192];
				int len;
				int16_t blank[2048] = { 0 }, *r = NULL;

				if (context->channels == 2) {
					r = blank;
				}

				len = lame_encode_buffer(context->gfp, blank, r, sizeof(blank) / 2, mp3buffer, sizeof(mp3buffer));

				if (len) {
					ret = shout_send(context->shout, mp3buffer, len);
					if (ret == SHOUTERR_SUCCESS) {
						shout_sync(context->shout);
					}
				}

				while ((len = lame_encode_flush(context->gfp, mp3buffer, sizeof(mp3buffer))) > 0) {
					ret = shout_send(context->shout, mp3buffer, len);

					if (ret != SHOUTERR_SUCCESS) {
						break;
					} else {
						shout_sync(context->shout);
					}
				}
			}

			shout_close(context->shout);
			context->shout = NULL;
		}

		if (context->gfp) {
			lame_close(context->gfp);
			context->gfp = NULL;
		}

		if (context->audio_buffer) {
			switch_buffer_destroy(&context->audio_buffer);
		}

		switch_mutex_destroy(context->audio_mutex);

		switch_thread_rwlock_unlock(context->rwlock);
		switch_thread_rwlock_destroy(context->rwlock);
	}
}
static void *SWITCH_THREAD_FUNC write_stream_thread(switch_thread_t *thread, void *obj)
{
	shout_context_t *context = (shout_context_t *) obj;

	switch_thread_rwlock_rdlock(context->rwlock);

	if (context->thread_running) {
		context->thread_running++;
	} else {
		switch_thread_rwlock_unlock(context->rwlock);
		return NULL;
	}

	if (!context->lame_ready) {
		lame_init_params(context->gfp);
		lame_print_config(context->gfp);
		context->lame_ready = 1;
	}

	while (!context->err && context->thread_running) {
		unsigned char mp3buf[20480] = "";
		int16_t audio[9600] = { 0 };
		switch_size_t audio_read = 0;
		int rlen = 0;
		long ret = 0;

		switch_mutex_lock(context->audio_mutex);
		if (context->audio_buffer) {
			audio_read = switch_buffer_read(context->audio_buffer, audio, sizeof(audio));
		} else {
			context->err++;
		}
		switch_mutex_unlock(context->audio_mutex);

		error_check();

		if (!audio_read) {
			audio_read = sizeof(audio);
			memset(audio, 255, sizeof(audio));
		}

		if (context->channels == 2) {
			int16_t l[4800] = { 0 };
			int16_t r[4800] = { 0 };
			int j = 0;
			switch_size_t i;

			for (i = 0; i < audio_read / 4; i++) {
				l[i] = audio[j++];
				r[i] = audio[j++];
			}

			if ((rlen = lame_encode_buffer(context->gfp, l, r, audio_read / 4, mp3buf, sizeof(mp3buf))) < 0) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "MP3 encode error %d!\n", rlen);
				goto error;
			}

		} else if (context->channels == 1) {
			if ((rlen = lame_encode_buffer(context->gfp, (void *) audio, NULL, audio_read / sizeof(int16_t), mp3buf, sizeof(mp3buf))) < 0) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "MP3 encode error %d!\n", rlen);
				goto error;
			}
		}

		if (rlen) {
			ret = shout_send(context->shout, mp3buf, rlen);
			if (ret != SHOUTERR_SUCCESS) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Send error: %s\n", shout_get_error(context->shout));
				goto error;
			}
		} else {
			memset(mp3buf, 0, 128);
			ret = shout_send(context->shout, mp3buf, 128);
		}

		shout_sync(context->shout);
		switch_yield(100000);
	}

  error:
	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Write Thread Done\n");
	switch_thread_rwlock_unlock(context->rwlock);
	context->thread_running = 0;
	return NULL;
}
void do_telecast(switch_stream_handle_t *stream)
{
	char *path_info = switch_event_get_header(stream->param_event, "http-path-info");
	char *uuid = strdup(path_info + 4);
	switch_core_session_t *tsession;
	char *fname = "stream.mp3";

	if ((fname = strchr(uuid, '/'))) {
		*fname++ = '\0';
	}

	if (!(tsession = switch_core_session_locate(uuid))) {
		char *ref = switch_event_get_header(stream->param_event, "http-referer");
		stream->write_function(stream, "Content-type: text/html\r\n\r\n<h2>Not Found!</h2>\n" "<META http-equiv=\"refresh\" content=\"1;URL=%s\">", ref);
	} else {
		switch_media_bug_t *bug = NULL;
		switch_buffer_t *buffer = NULL;
		switch_mutex_t *mutex;
		switch_channel_t *channel = switch_core_session_get_channel(tsession);
		lame_global_flags *gfp = NULL;
		switch_codec_implementation_t read_impl = { 0 };
		switch_core_session_get_read_impl(tsession, &read_impl);

		if (switch_channel_test_flag(channel, CF_PROXY_MODE)) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Stepping into media path so this will work!\n");
			switch_ivr_media(uuid, SMF_REBRIDGE);
		}

		if (!(gfp = lame_init())) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not allocate lame\n");
			goto end;
		}
		lame_set_num_channels(gfp, read_impl.number_of_channels);
		lame_set_in_samplerate(gfp, read_impl.actual_samples_per_second);
		lame_set_brate(gfp, 16 * (read_impl.actual_samples_per_second / 8000) * read_impl.number_of_channels);
		lame_set_mode(gfp, 3);
		lame_set_quality(gfp, 2);
		lame_set_errorf(gfp, log_error);
		lame_set_debugf(gfp, log_debug);
		lame_set_msgf(gfp, log_msg);
		lame_set_bWriteVbrTag(gfp, 0);
		lame_mp3_tags_fid(gfp, NULL);
		lame_init_params(gfp);
		lame_print_config(gfp);

		switch_mutex_init(&mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(tsession));
		switch_buffer_create_dynamic(&buffer, 1024, 2048, 0);
		switch_buffer_add_mutex(buffer, mutex);

		if (switch_core_media_bug_add(tsession, "telecast", NULL,
									  telecast_callback, buffer, 0,
									  SMBF_READ_STREAM | SMBF_WRITE_STREAM | SMBF_READ_PING, &bug) != SWITCH_STATUS_SUCCESS) {
			goto end;
		}

		stream->write_function(stream, "Content-type: audio/mpeg\r\n" "Content-Disposition: inline; filename=\"%s\"\r\n\r\n", fname);

		while (switch_channel_ready(channel)) {
			unsigned char mp3buf[TC_BUFFER_SIZE] = "";
			int rlen;
			uint8_t buf[1024];
			switch_size_t bytes = 0;

			if (switch_buffer_inuse(buffer) >= 1024) {
				switch_buffer_lock(buffer);
				bytes = switch_buffer_read(buffer, buf, sizeof(buf));
				switch_buffer_unlock(buffer);
			} else {
				if (!bytes) {
					switch_cond_next();
					continue;
				}
				memset(buf, 0, bytes);
			}

			if ((rlen = lame_encode_buffer(gfp, (void *) buf, NULL, bytes / 2, mp3buf, sizeof(mp3buf))) < 0) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "MP3 encode error %d!\n", rlen);
				goto end;
			}

			if (rlen) {
				if (stream->raw_write_function(stream, mp3buf, rlen)) {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Disconnected\n");
					goto end;
				}
			}
		}

	  end:

		switch_safe_free(uuid);

		if (gfp) {
			lame_close(gfp);
			gfp = NULL;
		}

		if (bug) {
			switch_core_media_bug_remove(tsession, &bug);
		}

		if (buffer) {
			switch_buffer_destroy(&buffer);
		}

		switch_core_session_rwunlock(tsession);
	}
}
void do_broadcast(switch_stream_handle_t *stream)
{
	char *path_info = switch_event_get_header(stream->param_event, "http-path-info");
	char *file;
	lame_global_flags *gfp = NULL;
	switch_file_handle_t fh = { 0 };
	unsigned char mp3buf[TC_BUFFER_SIZE] = "";
	uint8_t buf[1024];
	int rlen;
	int is_local = 0;
	uint32_t interval = 20000;

	if (strstr(path_info + 7, "://")) {
		file = strdup(path_info + 7);
		is_local++;
	} else {
		file = switch_mprintf("%s/streamfiles/%s", SWITCH_GLOBAL_dirs.base_dir, path_info + 7);
	}
	assert(file);

	if (switch_core_file_open(&fh, file, 0, 0, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) {
		memset(&fh, 0, sizeof(fh));
		stream->write_function(stream, "Content-type: text/html\r\n\r\n<h2>File not found</h2>\n");
		goto end;
	}

	if (switch_test_flag((&fh), SWITCH_FILE_NATIVE)) {
		stream->write_function(stream, "Content-type: text/html\r\n\r\n<h2>File format not supported</h2>\n");
		goto end;
	}

	if (!(gfp = lame_init())) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not allocate lame\n");
		goto end;
	}

	lame_set_num_channels(gfp, fh.channels);
	lame_set_in_samplerate(gfp, fh.samplerate);
	lame_set_brate(gfp, 16 * (fh.samplerate / 8000) * fh.channels);
	lame_set_mode(gfp, 3);
	lame_set_quality(gfp, 2);
	lame_set_errorf(gfp, log_error);
	lame_set_debugf(gfp, log_debug);
	lame_set_msgf(gfp, log_msg);
	lame_set_bWriteVbrTag(gfp, 0);
	lame_mp3_tags_fid(gfp, NULL);
	lame_init_params(gfp);
	lame_print_config(gfp);

	stream->write_function(stream, "Content-type: audio/mpeg\r\n" "Content-Disposition: inline; filename=\"%s.mp3\"\r\n\r\n", path_info + 7);

	if (fh.interval) {
		interval = fh.interval * 1000;
	}

	for (;;) {
		switch_size_t samples = sizeof(buf) / 2;

		switch_core_file_read(&fh, buf, &samples);

		if (is_local) {
			switch_yield(interval);
		}

		if (!samples) {
			break;
		}

		if ((rlen = lame_encode_buffer(gfp, (void *) buf, NULL, samples, mp3buf, sizeof(mp3buf))) < 0) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "MP3 encode error %d!\n", rlen);
			goto end;
		}

		if (rlen) {
			if (stream->raw_write_function(stream, mp3buf, rlen)) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Disconnected\n");
				goto end;
			}
		}
	}

	while ((rlen = lame_encode_flush(gfp, mp3buf, sizeof(mp3buf))) > 0) {
		if (stream->raw_write_function(stream, mp3buf, rlen)) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Disconnected\n");
			goto end;
		}
	}

  end:

	if (fh.channels) {
		switch_core_file_close(&fh);
	}

	switch_safe_free(file);

	if (gfp) {
		lame_close(gfp);
		gfp = NULL;
	}
}
Example #11
0
void *encode(void *init) {
   
    char file[256];
    int  fd1 = -1, fd2 = -1, fd_out = -1;
    uint32_t i, k;
    int16_t *b0 = 0, *b1 = 0, *b2 = 0;
    rec_ctx *ctx = (rec_ctx *) init;	

#ifdef USING_LAME
    lame_global_flags *gfp;
#endif
	log_info("in encode thread");

	pthread_join(ctx->rec1,0);
	pthread_join(ctx->rec2,0);

	log_info("recorder threads complete, encoding");

	sprintf(file, OUT_DIR "/%s-up",ctx->cur_file);
	fd1 = open(file,O_RDONLY);
	sprintf(file, OUT_DIR "/%s-dn",ctx->cur_file);
	fd2 = open(file,O_RDONLY);
	if(fd1 < 0 || fd2 < 0) {
	     if(fd1 >= 0) { 
		close(fd1); sprintf(file, OUT_DIR "/%s-up",ctx->cur_file); unlink(file);
	     }	
	     if(fd2 >= 0) {
		close(fd2); sprintf(file, OUT_DIR "/%s-dn",ctx->cur_file); unlink(file);
	     }	
	     log_err("encode: input file not found");
	     return 0;		
	}

#ifdef USING_LAME
     if(ctx->ismp3) 
        sprintf(file, OUT_DIR "/%s.mp3",ctx->cur_file);
     else 
#endif
	sprintf(file, OUT_DIR "/%s.wav",ctx->cur_file);

	fd_out = open(file,O_CREAT|O_TRUNC|O_WRONLY);
	if(fd_out < 0) {
	     log_err("encode: cannot open output file %s",file);
             close(fd1); sprintf(file, OUT_DIR "/%s-up",ctx->cur_file); unlink(file);
             close(fd2); sprintf(file, OUT_DIR "/%s-dn",ctx->cur_file); unlink(file);
	     return 0;		
	}

	i = (uint32_t) lseek(fd1,0,SEEK_END);
	k = (uint32_t) lseek(fd2,0,SEEK_END);
	lseek(fd1,0,SEEK_SET);
	lseek(fd2,0,SEEK_SET);

	if(i != k) {
	     log_info("file sizes mismatch");	
	     if(i > k) i = k;	    		
	}
	i &= ~1;
	if(i == 0) {
	     log_err("zero size input file");
	     close(fd_out); unlink(file);
	     close(fd1); sprintf(file, OUT_DIR "/%s-up",ctx->cur_file); unlink(file);		
	     close(fd2); sprintf(file, OUT_DIR "/%s-dn",ctx->cur_file); unlink(file);
	     return 0;			
	}

#ifdef USING_LAME
     if(ctx->ismp3) {
	gfp = lame_init();
	lame_set_errorf(gfp,lame_error_handler);
	lame_set_debugf(gfp,lame_error_handler);
	lame_set_msgf(gfp,lame_error_handler);
	lame_set_num_channels(gfp,2);
	lame_set_in_samplerate(gfp,8000);
	lame_set_brate(gfp,64); /* compress 1:4 */
	lame_set_mode(gfp,0);	/* mode = stereo */
	lame_set_quality(gfp,2);   /* 2=high  5 = medium  7=low */ 
	if(lame_init_params(gfp) < 0) {
	     log_err("encode: failed to init lame"); 	
             close(fd_out); unlink(file);
             close(fd1); sprintf(file, OUT_DIR "/%s-up",ctx->cur_file); unlink(file);
             close(fd2); sprintf(file, OUT_DIR "/%s-dn",ctx->cur_file); unlink(file);
	     return 0;			
	}
#define CHSZ (512*1024)
#define OCHSZ (5*(CHSZ/8)+7200) 
	b0 = (int16_t *) malloc(OCHSZ);
        b1 = (int16_t *) malloc(CHSZ);
        b2 = (int16_t *) malloc(CHSZ);
        if(!b0 || !b1 || !b2) {
             log_err("encode: out of memory");
	     if(b0) free(b0);
             if(b1) free(b1);
             if(b2) free(b2);
             close(fd_out); unlink(file);
             close(fd1); sprintf(file, OUT_DIR "/%s-up",ctx->cur_file); unlink(file);
             close(fd2); sprintf(file, OUT_DIR "/%s-dn",ctx->cur_file); unlink(file);
             return 0;
        }
	k = 0;
	do {
	   int ret = 0;	
	   uint32_t j = 0, count = 0;
	   unsigned char *c1,*c2;	
	     for(c1 = (unsigned char*) b1, c2 = (unsigned char*) b2; count < CHSZ; c1 += ret, c2 += ret) {
		j = (k + RSZ > i) ? i - k : RSZ;
		ret = read(fd1,c1,j);
		if(ret < 0) break;
		ret = read(fd2,c2,j);
		if(ret < 0) break;
		k += ret; count += ret;
		if(k == i) break;
	     }
	     if(ret < 0) break;	
	     if(count) {
		ret = lame_encode_buffer(gfp,b1,b2,count/2,(unsigned char *)b0,OCHSZ);
		if(ret < 0) break;
		c1 = (unsigned char *) b0;
		count = ret;
		for(j = 0; j < count; j += RSZ, c1 += ret) {
		     ret = (j + RSZ > count) ? count - j : RSZ;
		     write(fd_out,c1,ret);
		}		
	     }				
	} while(k < i);

	i = (uint32_t) lame_encode_flush(gfp,(unsigned char *)b0,OCHSZ);
	if(i) write(fd_out,b0,i);
	lame_close(gfp);
     } else {		
#endif
        b0 = (int16_t *) malloc(RSZ*2);
        b1 = (int16_t *) malloc(RSZ);
        b2 = (int16_t *) malloc(RSZ);
        if(!b0 || !b1 || !b2) {
             log_err("encode: out of memory");
             if(b0) free(b0);
             if(b1) free(b1);
             if(b2) free(b2);
             close(fd_out); unlink(file);
             close(fd1); sprintf(file, OUT_DIR "/%s-up",ctx->cur_file); unlink(file);
             close(fd2); sprintf(file, OUT_DIR "/%s-dn",ctx->cur_file); unlink(file);
             return 0;
        }
	wavhdr.data_sz = i*2;
	wavhdr.riff_sz = i*2 + 36; 
	write(fd_out,&wavhdr,sizeof(wavhdr));
	k = 0;		
	while(1) {
	    uint32_t j, count = (k + RSZ > i) ? i - k : RSZ;
		if(read(fd1,b1,count) < 0) break;
		if(read(fd2,b2,count) < 0) break;
		for(j = 0; j < count/2; j++) {
		      b0[2*j] = b1[j];  b0[2*j+1] = b2[j];
		}			
		write(fd_out,b0,count*2);			
		k += count;
		if(k == i) break;
	}
#ifdef USING_LAME
    }
#endif
	close(fd1); close(fd2); close(fd_out);
	free(b0); free(b1); free(b2);	
	log_info("encoding complete");

	sprintf(file, OUT_DIR "/%s-up",ctx->cur_file); unlink(file);
	sprintf(file, OUT_DIR "/%s-dn",ctx->cur_file); unlink(file);

	free(ctx->x);
	free(ctx);

    return 0; 
}
Example #12
0
int lame_encode_buffer_interleaved(lame_global_flags *gfp,
   short int buffer[], int nsamples, char *mp3buf, int mp3buf_size)
{
  static int frame_buffered=0;
  int mp3size=0,ret,i,ch,mf_needed;

  /* some sanity checks */
  assert(ENCDELAY>=MDCTDELAY);
  assert(BLKSIZE-FFTOFFSET >= 0);
  mf_needed = BLKSIZE+gfp->framesize-FFTOFFSET;
  assert(MFSIZE>=mf_needed);

  if (gfp->num_channels == 1) {
    return lame_encode_buffer(gfp,buffer, NULL ,nsamples,mp3buf,mp3buf_size);
  }

  if (gfp->resample_ratio!=1)  {
    short int *buffer_l;
    short int *buffer_r;
    buffer_l=malloc(sizeof(short int)*nsamples);
    buffer_r=malloc(sizeof(short int)*nsamples);
    if (buffer_l == NULL || buffer_r == NULL) {
      return -1;
    }
    for (i=0; i<nsamples; i++) {
      buffer_l[i]=buffer[2*i];
      buffer_r[i]=buffer[2*i+1];
    }
    ret = lame_encode_buffer(gfp,buffer_l,buffer_r,nsamples,mp3buf,mp3buf_size);
    free(buffer_l);
    free(buffer_r);
    return ret;
  }


  if (gfp->frameNum==0 && !frame_buffered) {
    memset((char *) mfbuf, 0, sizeof(mfbuf));
    frame_buffered=1;
    mf_samples_to_encode = ENCDELAY+288;
    mf_size=ENCDELAY-MDCTDELAY;  /* we pad input with this many 0's */
  }
  if (gfp->frameNum==1) {
    /* reset, for the next time frameNum==0 */
    frame_buffered=0;
  }

  if (gfp->num_channels==2  && gfp->stereo==1) {
    /* downsample to mono */
    for (i=0; i<nsamples; ++i) {
      buffer[2*i]=((int)buffer[2*i]+(int)buffer[2*i+1])/2;
      buffer[2*i+1]=0;
    }
  }


  while (nsamples > 0) {
    int n_out;
    /* copy in new samples */
    n_out = Min(gfp->framesize,nsamples);
    for (i=0; i<n_out; ++i) {
      mfbuf[0][mf_size+i]=buffer[2*i];
      mfbuf[1][mf_size+i]=buffer[2*i+1];
    }
    buffer += 2*n_out;

    nsamples -= n_out;
    mf_size += n_out;
    assert(mf_size<=MFSIZE);
    mf_samples_to_encode += n_out;

    if (mf_size >= mf_needed) {
      /* encode the frame */
      ret = lame_encode_frame(gfp,mfbuf[0],mfbuf[1],mf_size,mp3buf,mp3buf_size);
      if (ret == -1) {
	/* fatel error: mp3buffer was too small */
	return -1;
      }
      mp3buf += ret;
      mp3size += ret;

      /* shift out old samples */
      mf_size -= gfp->framesize;
      mf_samples_to_encode -= gfp->framesize;
      for (ch=0; ch<gfp->stereo; ch++)
	for (i=0; i<mf_size; i++)
	  mfbuf[ch][i]=mfbuf[ch][i+gfp->framesize];
    }
  }
  assert(nsamples==0);
  return mp3size;
}
Example #13
0
int
CEncoderLame::encode(const sp<IMediaSource>& pMediaSource_in, const sp<IAudioSink>& pAudioSink_out)
{
    AUTO_LOG();

    CHECK_PTR_EXT(m_pGobalFlags, BAD_VALUE);
    CHECK_PTR_EXT(pMediaSource_in, BAD_VALUE);
    CHECK_PTR_EXT(pAudioSink_out, BAD_VALUE);

    sp<MetaData>  pMeta = pMediaSource_in->getFormat();
    CHECK_PTR_EXT(pMeta,  BAD_VALUE);

    int32_t iChannelNum = 0;
    bool chk = pMeta->findInt32(kKeyChannelCount, &iChannelNum);
    CHECK_IS_EXT((true == chk), UNKNOWN_ERROR);
    int  ret = lame_set_num_channels(m_pGobalFlags, iChannelNum);
    CHECK_IS_EXT((ret == OK), ret);

    // only support one channel and two channels
    CHECK_IS_EXT(((1 == iChannelNum) || (2 == iChannelNum)), INVALID_OPERATION);

    ret = pMediaSource_in->start();
    CHECK_IS_EXT((ret == OK), ret);

    MediaBuffer* pBuf = NULL;

    while (OK == (pMediaSource_in->read(&pBuf, NULL))) {
        if (pBuf == NULL) {
            break;
        }

        if ((pBuf->data() == NULL) || (pBuf->range_length() == 0)) {
            pBuf->release();
            pBuf = NULL;
            continue;
        }

        int16_t *pOrg = (int16_t *)((const char *)pBuf->data() + pBuf->range_offset());
        ssize_t iSamplesRead = pBuf->range_length() / 2;
        pOrg += iSamplesRead;
        iSamplesRead /= iChannelNum;

        CHECK_NE(iSamplesRead, 0);

        int iMP3BufSize = 1.25 * iSamplesRead + 7200;
        short int*     pPCMBufL = new short int[iSamplesRead];
        short int*     pPCMBufR = new short int[iSamplesRead];
        unsigned char* pMP3Buf  = new unsigned char[iMP3BufSize];

        if (iChannelNum == 2) {
            for (ssize_t i = iSamplesRead; --i >= 0;) {
                pPCMBufR[i] = *--pOrg;
                pPCMBufL[i] = *--pOrg;
            }
        } else if (iChannelNum == 1) {
            memset(pPCMBufR, 0, iSamplesRead * sizeof(short int));

            for (ssize_t i = iSamplesRead; --i >= 0;) {
                pPCMBufL[i] = *--pOrg;
            }
        } else {
            // EMPTY
        }

        int iOutSize = lame_encode_buffer(m_pGobalFlags, pPCMBufL, pPCMBufR, iSamplesRead, pMP3Buf, iMP3BufSize);
        int iWriteSize = iOutSize;

        if (iOutSize > 0) {
            iWriteSize = pAudioSink_out->write(pMP3Buf, iOutSize);
        }

        delete (pMP3Buf);
        delete (pPCMBufR);
        delete (pPCMBufL);


        pBuf->release();
        pBuf = NULL;

        CHECK_IS_EXT((iOutSize == iWriteSize), UNKNOWN_ERROR);
    }

    // last frame may remain
    {
        unsigned char* pMP3Buf  = new unsigned char[LAME_MAXMP3BUFFER];
        int iOutSize = lame_encode_flush(m_pGobalFlags, pMP3Buf, sizeof(pMP3Buf));
        int iWriteSize = iOutSize;

        if (iOutSize > 0) {
            iWriteSize = pAudioSink_out->write(pMP3Buf, iOutSize);
        }

        delete (pMP3Buf);

        CHECK_IS_EXT((iOutSize == iWriteSize), UNKNOWN_ERROR);
    }

    // write the tag3v1
    {
        unsigned char* pMP3Buf = new unsigned char[128];
        int iOutSize = lame_get_id3v1_tag(m_pGobalFlags, pMP3Buf, sizeof(pMP3Buf));
        int iWriteSize = iOutSize;

        if ((iOutSize > 0) && (((size_t)iOutSize) <= sizeof(pMP3Buf))) {
            iWriteSize = pAudioSink_out->write(pMP3Buf, iOutSize);
        }

        delete (pMP3Buf);

        CHECK_IS_EXT((iOutSize == iWriteSize), UNKNOWN_ERROR);
    }

    RETURN(OK);
}
bool Mp3Writer::write(QByteArray &left, QByteArray &right, long samples, bool flush) {
	int ret;
	QByteArray output;
	// rough upper bound formula taken from lame.h
	long size = samples + samples / 4 + 7200;

	do {
		output.resize(size);

		if (stereo) {
			ret = lame_encode_buffer(lame, reinterpret_cast<const short *>(left.constData()),
				reinterpret_cast<const short *>(right.constData()), samples,
				reinterpret_cast<unsigned char *>(output.data()), output.size());
		} else {
			// lame.h claims to write to the buffers, even though they're declared const, be safe
			// TODO: this mixes both channels again!  can lame take only mono samples?
			ret = lame_encode_buffer(lame, reinterpret_cast<const short *>(left.data()),
				reinterpret_cast<const short *>(left.data()), samples,
				reinterpret_cast<unsigned char *>(output.data()), output.size());
		}

		if (ret == -1) {
			// there wasn't enough space in output
			size *= 2;
			continue;
		}
	} while (false);

	if (ret < 0) {
		debug(QString("Error while writing MP3 file, code = %1").arg(ret));
		return false;
	}

	samplesWritten += samples;

	if (ret > 0) {
		output.truncate(ret);
		file.write(output);
	}

	left.remove(0, samples * 2);
	if (stereo)
		right.remove(0, samples * 2);

	if (!flush)
		return true;

	// flush mp3

	output.resize(10240);
	ret = lame_encode_flush(lame, reinterpret_cast<unsigned char *>(output.data()), output.size());

	lame_close(lame);
	lame = NULL;
	hasFlushed = true;

	if (ret < 0) {
		debug(QString("Error while flushing MP3 file, code = %1").arg(ret));
		return false;
	}

	if (ret > 0) {
		output.truncate(ret);
		file.write(output);
	}

	return true;
}
Example #15
0
int main(int argc, char **argv)
{

  char mp3buffer[LAME_MAXMP3BUFFER];
  short int Buffer[2][1152];
  int iread,imp3;
  lame_global_flags gf;
  FILE *outf;
#ifdef __riscos__
  int i;
#endif


  lame_init(&gf);                  /* initialize libmp3lame */
  if(argc==1) lame_usage(&gf,argv[0]);  /* no command-line args, print usage, exit  */

  /* parse the command line arguments, setting various flags in the
   * struct 'gf'.  If you want to parse your own arguments,
   * or call libmp3lame from a program which uses a GUI to set arguments,
   * skip this call and set the values of interest in the gf struct.
   * (see lame.h for documentation about these parameters)
   */
  lame_parse_args(&gf,argc, argv);

  if (!gf.gtkflag) {
    /* open the MP3 output file */
    if (!strcmp(gf.outPath, "-")) {
#ifdef __EMX__
      _fsetmode(stdout,"b");
#elif (defined  __BORLANDC__)
      setmode(_fileno(stdout), O_BINARY);
#elif (defined  __CYGWIN__)
      setmode(fileno(stdout), _O_BINARY);
#elif (defined _WIN32)
      _setmode(_fileno(stdout), _O_BINARY);
#endif
      outf = stdout;
    } else {
      if ((outf = fopen(gf.outPath, "wb")) == NULL) {
	fprintf(stderr,"Could not create \"%s\".\n", gf.outPath);
	exit(1);
      }
    }
#ifdef __riscos__
    /* Assign correct file type */
    for (i = 0; gf.outPath[i]; i++)
      if (gf.outPath[i] == '.') gf.outPath[i] = '/';
    SetFiletype(gf.outPath, 0x1ad);
#endif
  }


  /* open the wav/aiff/raw pcm or mp3 input file.  This call will
   * open the file with name gf.inFile, try to parse the headers and
   * set gf.samplerate, gf.num_channels, gf.num_samples.
   * if you want to do your own file input, skip this call and set
   * these values yourself.
   */
  lame_init_infile(&gf);

  /* Now that all the options are set, lame needs to analyze them and
   * set some more options
   */
  lame_init_params(&gf);
  lame_print_config(&gf);   /* print usefull information about options being used */




#ifdef HAVEGTK
  if (gf.gtkflag) gtk_init (&argc, &argv);
  if (gf.gtkflag) gtkcontrol(&gf);
  else
#endif
    {

      /* encode until we hit eof */
      do {
	/* read in 'iread' samples */
	iread=lame_readframe(&gf,Buffer);


	/* encode */
	imp3=lame_encode_buffer(&gf,Buffer[0],Buffer[1],iread,
              mp3buffer,(int)sizeof(mp3buffer)); 

	/* was our output buffer big enough? */
	if (imp3==-1) {
	  fprintf(stderr,"mp3 buffer is not big enough... \n");
	  exit(1);
	}

	if (fwrite(mp3buffer,1,imp3,outf) != imp3) {
	  fprintf(stderr,"Error writing mp3 output");
	  exit(1);
	}
      } while (iread);
    }

  imp3=lame_encode_finish(&gf,mp3buffer,(int)sizeof(mp3buffer));   /* may return one more mp3 frame */
  fwrite(mp3buffer,1,imp3,outf);
  fclose(outf);
  lame_close_infile(&gf);            /* close the input file */
  lame_mp3_tags(&gf);                /* add id3 or VBR tags to mp3 file */
  return 0;
}