Пример #1
0
FLACSource::FLACSource(const FLACModule &module,
                       const std::shared_ptr<FILE> &fp):
    m_eof(false),
    m_giveup(false),
    m_initialize_done(false),
    m_length(0),
    m_position(0),
    m_fp(fp),
    m_module(module)
{
    char buffer[33];
    util::check_eof(util::nread(fileno(m_fp.get()), buffer, 33) == 33);
    if (std::memcmp(buffer, "ID3", 3) == 0) {
        uint32_t size = 0;
        for (int i = 6; i < 10; ++i) {
            size <<= 7;
            size |= buffer[i];
        }
        CHECKCRT(_lseeki64(fileno(m_fp.get()), 10 + size, SEEK_SET) < 0);
        util::check_eof(util::nread(fileno(m_fp.get()), buffer, 33) == 33);
    }
    uint32_t fcc = util::fourcc(buffer);
    if ((fcc != 'fLaC' && fcc != 'OggS')
     || (fcc == 'OggS' && std::memcmp(&buffer[28], "\177FLAC", 5)))
        throw std::runtime_error("Not a FLAC file");
    CHECKCRT(_lseeki64(fileno(m_fp.get()), 0, SEEK_SET) < 0);

    m_decoder =
        decoder_t(m_module.stream_decoder_new(),
                  std::bind1st(std::mem_fun(&FLACSource::close), this));
    TRYFL(m_module.stream_decoder_set_metadata_respond(
                m_decoder.get(), FLAC__METADATA_TYPE_VORBIS_COMMENT));
    TRYFL(m_module.stream_decoder_set_metadata_respond(
                m_decoder.get(), FLAC__METADATA_TYPE_PICTURE));

    TRYFL((fcc == 'OggS' ? m_module.stream_decoder_init_ogg_stream
                         : m_module.stream_decoder_init_stream)
            (m_decoder.get(),
             staticReadCallback,
             staticSeekCallback,
             staticTellCallback,
             staticLengthCallback,
             staticEofCallback,
             staticWriteCallback,
             staticMetadataCallback,
             staticErrorCallback,
             this) == FLAC__STREAM_DECODER_INIT_STATUS_OK);
    TRYFL(m_module.stream_decoder_process_until_end_of_metadata(
                m_decoder.get()));
    if (m_giveup || m_asbd.mBitsPerChannel == 0)
        flac::want(false);
    m_buffer.set_unit(m_asbd.mChannelsPerFrame);
    m_initialize_done = true;
}
Пример #2
0
void FLACSource::seekTo(int64_t count)
{
    if (count == m_position)
        return;
    m_buffer.reset();
    TRYFL(m_module.stream_decoder_seek_absolute(m_decoder.get(), count));
    m_position = count;
}
Пример #3
0
size_t FLACSource::readSamples(void *buffer, size_t nsamples)
{
    if (m_giveup)
        throw std::runtime_error("FLAC decoder error");
    if (!m_buffer.count()) {
        if (m_module.stream_decoder_get_state(m_decoder.get()) ==
                FLAC__STREAM_DECODER_END_OF_STREAM)
            return 0;
        TRYFL(m_module.stream_decoder_process_single(m_decoder.get()));
    }
    uint32_t count = std::min(m_buffer.count(), nsamples);
    if (count) {
        uint32_t bytes = count * m_asbd.mChannelsPerFrame * 4;
        std::memcpy(buffer, m_buffer.read(count), bytes);
        m_position += count;
    }
    return count;
}
Пример #4
0
FLACSink::FLACSink(FILE *fp, uint64_t duration, const SampleFormat &fmt,
		   const FLACModule &module,
		   const std::map<uint32_t, std::wstring> &tags)
    :m_fp(fp), m_module(module), m_format(fmt)
{
    if (fmt.m_type == SampleFormat::kIsFloat)
	throw std::runtime_error("Can't handle float source");
    if (fmt.m_endian == SampleFormat::kIsBigEndian)
	throw std::runtime_error("Can't handle big endian source");
    m_encoder.swap(encoder_t(m_module.stream_encoder_new(),
		std::bind1st(std::mem_fun(&FLACSink::closeEncoder), this)));
    TRYFL(m_module.stream_encoder_set_channels(
		m_encoder.get(), fmt.m_nchannels));
    TRYFL(m_module.stream_encoder_set_bits_per_sample(
		m_encoder.get(), fmt.m_bitsPerSample));
    TRYFL(m_module.stream_encoder_set_sample_rate(
		m_encoder.get(), fmt.m_rate));
    TRYFL(m_module.stream_encoder_set_total_samples_estimate(
		m_encoder.get(), duration));
    TRYFL(m_module.stream_encoder_set_compression_level(
		m_encoder.get(), 5));

    FLAC__StreamMetadata *meta[2];
    meta[0] =
	m_module.metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT);
    meta[1] = m_module.metadata_object_new(FLAC__METADATA_TYPE_PADDING);
    meta[1]->length = 0x1000;
    m_metadata_holder[0].swap(
	    metadata_t(meta[0], m_module.metadata_object_delete));
    m_metadata_holder[1].swap(
	    metadata_t(meta[1], m_module.metadata_object_delete));
    {
	FLAC__StreamMetadata_VorbisComment_Entry entry;
	std::map<uint32_t, std::wstring>::const_iterator ii;
	utf8_codecvt_facet u8codec;
	for (ii = tags.begin(); ii != tags.end(); ++ii) {
	    const char *key = GetNameFromTagID(ii->first);
	    if (!key) continue;
	    std::string value = w2m(ii->second, u8codec);
	    m_module.metadata_object_vorbiscomment_entry_from_name_value_pair(
		    &entry, key, value.c_str());
	    m_module.metadata_object_vorbiscomment_append_comment(
		    meta[0], entry, false);
	}
    }
    m_module.stream_encoder_set_metadata(m_encoder.get(), meta, 2);
    
    TRYFL(m_module.stream_encoder_init_stream(m_encoder.get(),
		staticWriteCallback, 0, 0, 0, this)
		    == FLAC__STREAM_ENCODER_INIT_STATUS_OK);
} 
Пример #5
0
void FLACSink::writeSamples(const void *data, size_t length, size_t nsamples)
{
    std::vector<int32_t> buff;
    switch (m_format.m_bitsPerSample) {
    case 8:
	{
	    const char *src = reinterpret_cast<const char *>(data);
	    for (size_t i = 0; i < length; ++i)
		buff.push_back(src[i]);
	}
	break;
    case 16:
	{
	    const int16_t *src = reinterpret_cast<const int16_t*>(data);
	    for (size_t i = 0; i < length / 2; ++i)
		buff.push_back(src[i]);
	}
	break;
    case 24:
	{
	    const uint8_t *src = reinterpret_cast<const uint8_t*>(data);
	    for (size_t i = 0; i < length / 3; ++i) {
		int32_t hv = static_cast<int8_t>(src[i*3+2]);
		int32_t v = (src[i*3] | (src[i*3+1] << 8) | (hv << 16));
		buff.push_back(v);
	    }
	}
	break;
    case 32:
	{
	    const int32_t *src = reinterpret_cast<const int32_t *>(data);
	    for (size_t i = 0; i < length / 4; ++i)
		buff.push_back(src[i]);
	}
	break;
    }
    TRYFL(m_module.stream_encoder_process_interleaved(
		m_encoder.get(), &buff[0], nsamples));
}