mirror of
https://github.com/holub/mame
synced 2025-04-19 15:11:37 +03:00
formats/flacfile.cpp: Added support for compact cassette images in FLAC format. (#11841)
This commit is contained in:
parent
3706aabe3d
commit
b9fbc6e7e9
@ -25,6 +25,7 @@ project "formats"
|
||||
MAME_DIR .. "src/lib/util",
|
||||
MAME_DIR .. "3rdparty",
|
||||
GEN_DIR,
|
||||
ext_includedir("flac"),
|
||||
ext_includedir("zlib"),
|
||||
}
|
||||
|
||||
@ -37,6 +38,8 @@ project "formats"
|
||||
|
||||
MAME_DIR .. "src/lib/formats/cassimg.cpp",
|
||||
MAME_DIR .. "src/lib/formats/cassimg.h",
|
||||
MAME_DIR .. "src/lib/formats/flacfile.cpp",
|
||||
MAME_DIR .. "src/lib/formats/flacfile.h",
|
||||
MAME_DIR .. "src/lib/formats/wavfile.cpp",
|
||||
MAME_DIR .. "src/lib/formats/wavfile.h",
|
||||
|
||||
|
@ -136,6 +136,7 @@ public:
|
||||
uint8_t image_read_byte(uint64_t offset);
|
||||
void image_write(const void *buffer, uint64_t offset, size_t length);
|
||||
uint64_t image_size();
|
||||
util::random_read_write::ptr &get_raw_cassette_image() { return m_io; }
|
||||
|
||||
// waveform accesses
|
||||
error get_samples(int channel,
|
||||
@ -191,6 +192,7 @@ public:
|
||||
|
||||
// builtin formats
|
||||
static const Format wavfile_format;
|
||||
static const Format flacfile_format;
|
||||
|
||||
private:
|
||||
struct manipulation_ranges;
|
||||
@ -224,7 +226,8 @@ private:
|
||||
#define CASSETTE_FORMATLIST_START(name) \
|
||||
const cassette_image::Format *const name[] = \
|
||||
{ \
|
||||
&cassette_image::wavfile_format,
|
||||
&cassette_image::wavfile_format, \
|
||||
&cassette_image::flacfile_format,
|
||||
#define CASSETTE_FORMAT(name) \
|
||||
&(name),
|
||||
#define CASSETTE_FORMATLIST_END \
|
||||
|
86
src/lib/formats/flacfile.cpp
Normal file
86
src/lib/formats/flacfile.cpp
Normal file
@ -0,0 +1,86 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Wilbert Pol
|
||||
/*********************************************************************
|
||||
|
||||
flacfile.cpp
|
||||
|
||||
Format code for flac files.
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
#include "flacfile.h"
|
||||
|
||||
#include "flac.h"
|
||||
|
||||
#include <memory>
|
||||
#include <new>
|
||||
|
||||
|
||||
static constexpr int MAX_CHANNELS = 8;
|
||||
|
||||
|
||||
static cassette_image::error flacfile_identify(cassette_image *cassette, cassette_image::Options *opts)
|
||||
{
|
||||
cassette->get_raw_cassette_image()->seek(0, SEEK_SET);
|
||||
flac_decoder decoder(*cassette->get_raw_cassette_image());
|
||||
if (!decoder.reset())
|
||||
return cassette_image::error::INVALID_IMAGE;
|
||||
const int channels = decoder.channels();
|
||||
const int sample_rate = decoder.sample_rate();
|
||||
const int bits_per_sample = decoder.bits_per_sample();
|
||||
const int total_samples = decoder.total_samples();
|
||||
decoder.finish();
|
||||
|
||||
opts->channels = channels;
|
||||
opts->sample_frequency = sample_rate;
|
||||
opts->bits_per_sample = bits_per_sample;
|
||||
|
||||
if (channels > MAX_CHANNELS)
|
||||
return cassette_image::error::INVALID_IMAGE;
|
||||
else if (channels > 0 && sample_rate > 0 && total_samples > 0)
|
||||
return cassette_image::error::SUCCESS;
|
||||
else
|
||||
return cassette_image::error::INVALID_IMAGE;
|
||||
}
|
||||
|
||||
|
||||
static cassette_image::error flacfile_load(cassette_image *cassette)
|
||||
{
|
||||
cassette->get_raw_cassette_image()->seek(0, SEEK_SET);
|
||||
flac_decoder decoder(*cassette->get_raw_cassette_image());
|
||||
if (!decoder.reset())
|
||||
return cassette_image::error::INVALID_IMAGE;
|
||||
const int channels = decoder.channels();
|
||||
const int total_samples = decoder.total_samples();
|
||||
|
||||
std::unique_ptr<int16_t []> samples[MAX_CHANNELS];
|
||||
int16_t *channel_samples[MAX_CHANNELS];
|
||||
for (int channel = 0; channel < channels; channel++)
|
||||
{
|
||||
samples[channel].reset(new (std::nothrow) int16_t [total_samples]);
|
||||
if (!samples[channel])
|
||||
return cassette_image::error::OUT_OF_MEMORY;
|
||||
channel_samples[channel] = samples[channel].get();
|
||||
}
|
||||
if (!decoder.decode(channel_samples, decoder.total_samples(), false))
|
||||
return cassette_image::error::INVALID_IMAGE;
|
||||
for (int channel = 0; channel < channels; channel++)
|
||||
{
|
||||
const cassette_image::error err = cassette->put_samples(
|
||||
channel, 0.0, (double)total_samples/decoder.sample_rate(), total_samples,
|
||||
2, channel_samples[channel], cassette_image::WAVEFORM_16BIT);
|
||||
if (err != cassette_image::error::SUCCESS)
|
||||
return err;
|
||||
}
|
||||
|
||||
return cassette_image::error::SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
const cassette_image::Format cassette_image::flacfile_format =
|
||||
{
|
||||
"flac",
|
||||
flacfile_identify,
|
||||
flacfile_load,
|
||||
nullptr
|
||||
};
|
10
src/lib/formats/flacfile.h
Normal file
10
src/lib/formats/flacfile.h
Normal file
@ -0,0 +1,10 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Wilbert Pol
|
||||
#ifndef MAME_FORMATS_FLACFILE_H
|
||||
#define MAME_FORMATS_FLACFILE_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cassimg.h"
|
||||
|
||||
#endif // MAME_FORMATS_FLACFILE_H
|
@ -316,6 +316,9 @@ flac_decoder::flac_decoder()
|
||||
flac_decoder::flac_decoder(const void *buffer, uint32_t length, const void *buffer2, uint32_t length2)
|
||||
: m_decoder(FLAC__stream_decoder_new()),
|
||||
m_file(nullptr),
|
||||
m_sample_rate(0),
|
||||
m_channels(0),
|
||||
m_bits_per_sample(0),
|
||||
m_compressed_offset(0),
|
||||
m_compressed_start(reinterpret_cast<const FLAC__byte *>(buffer)),
|
||||
m_compressed_length(length),
|
||||
@ -333,6 +336,9 @@ flac_decoder::flac_decoder(const void *buffer, uint32_t length, const void *buff
|
||||
flac_decoder::flac_decoder(util::read_stream &file)
|
||||
: m_decoder(FLAC__stream_decoder_new()),
|
||||
m_file(&file),
|
||||
m_sample_rate(0),
|
||||
m_channels(0),
|
||||
m_bits_per_sample(0),
|
||||
m_compressed_offset(0),
|
||||
m_compressed_start(nullptr),
|
||||
m_compressed_length(0),
|
||||
|
Loading…
Reference in New Issue
Block a user