3D Audio GSoC:
- Sequencer dynamics: Now it's possible to change the output channels and the resampling quality also increased (previously maximum quality was 44,1 kHz) - Changed two buffers to use ffmpeg allocation, not sure if that helps somehow.
This commit is contained in:
@@ -882,16 +882,11 @@ AUD_Handle* AUD_pauseAfter(AUD_Handle* handle, float seconds)
|
|||||||
|
|
||||||
AUD_Sound* AUD_createSequencer(int muted, void* data, AUD_volumeFunction volume)
|
AUD_Sound* AUD_createSequencer(int muted, void* data, AUD_volumeFunction volume)
|
||||||
{
|
{
|
||||||
/* AUD_XXX should be this: but AUD_createSequencer is called before the device
|
// specs are changed at a later point!
|
||||||
* is initialized.
|
|
||||||
|
|
||||||
return new AUD_SequencerFactory(AUD_device->getSpecs().specs, data, volume);
|
|
||||||
*/
|
|
||||||
AUD_Specs specs;
|
AUD_Specs specs;
|
||||||
specs.channels = AUD_CHANNELS_STEREO;
|
specs.channels = AUD_CHANNELS_STEREO;
|
||||||
specs.rate = AUD_RATE_44100;
|
specs.rate = AUD_RATE_44100;
|
||||||
AUD_Reference<AUD_SequencerFactory>* sequencer = new AUD_Reference<AUD_SequencerFactory>(new AUD_SequencerFactory(specs, muted, data, volume));
|
AUD_Reference<AUD_SequencerFactory>* sequencer = new AUD_Reference<AUD_SequencerFactory>(new AUD_SequencerFactory(specs, muted, data, volume));
|
||||||
(*sequencer)->setThis(sequencer);
|
|
||||||
return reinterpret_cast<AUD_Sound*>(sequencer);
|
return reinterpret_cast<AUD_Sound*>(sequencer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -928,6 +923,16 @@ void AUD_muteSequencer(AUD_Sound* sequencer, AUD_Reference<AUD_SequencerEntry>*
|
|||||||
((AUD_SequencerFactory*)sequencer->get())->mute(*entry, mute);
|
((AUD_SequencerFactory*)sequencer->get())->mute(*entry, mute);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AUD_setSequencerDeviceSpecs(AUD_Sound* sequencer)
|
||||||
|
{
|
||||||
|
((AUD_SequencerFactory*)sequencer->get())->setSpecs(AUD_device->getSpecs().specs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AUD_setSequencerSpecs(AUD_Sound* sequencer, AUD_Specs specs)
|
||||||
|
{
|
||||||
|
((AUD_SequencerFactory*)sequencer->get())->setSpecs(specs);
|
||||||
|
}
|
||||||
|
|
||||||
int AUD_readSound(AUD_Sound* sound, sample_t* buffer, int length)
|
int AUD_readSound(AUD_Sound* sound, sample_t* buffer, int length)
|
||||||
{
|
{
|
||||||
AUD_DeviceSpecs specs;
|
AUD_DeviceSpecs specs;
|
||||||
|
@@ -469,6 +469,10 @@ extern void AUD_moveSequencer(AUD_Sound* sequencer, AUD_SEntry* entry,
|
|||||||
extern void AUD_muteSequencer(AUD_Sound* sequencer, AUD_SEntry* entry,
|
extern void AUD_muteSequencer(AUD_Sound* sequencer, AUD_SEntry* entry,
|
||||||
char mute);
|
char mute);
|
||||||
|
|
||||||
|
extern void AUD_setSequencerDeviceSpecs(AUD_Sound* sequencer);
|
||||||
|
|
||||||
|
extern void AUD_setSequencerSpecs(AUD_Sound* sequencer, AUD_Specs specs);
|
||||||
|
|
||||||
extern int AUD_readSound(AUD_Sound* sound, sample_t* buffer, int length);
|
extern int AUD_readSound(AUD_Sound* sound, sample_t* buffer, int length);
|
||||||
|
|
||||||
extern void AUD_startPlayback(void);
|
extern void AUD_startPlayback(void);
|
||||||
|
@@ -44,6 +44,12 @@ AUD_ChannelMapperReader::~AUD_ChannelMapperReader()
|
|||||||
delete[] m_mapping;
|
delete[] m_mapping;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AUD_ChannelMapperReader::setChannels(AUD_Channels channels)
|
||||||
|
{
|
||||||
|
m_target_channels = channels;
|
||||||
|
calculateMapping();
|
||||||
|
}
|
||||||
|
|
||||||
float AUD_ChannelMapperReader::angleDistance(float alpha, float beta)
|
float AUD_ChannelMapperReader::angleDistance(float alpha, float beta)
|
||||||
{
|
{
|
||||||
alpha = fabs(alpha - beta);
|
alpha = fabs(alpha - beta);
|
||||||
|
@@ -109,6 +109,8 @@ public:
|
|||||||
*/
|
*/
|
||||||
~AUD_ChannelMapperReader();
|
~AUD_ChannelMapperReader();
|
||||||
|
|
||||||
|
void setChannels(AUD_Channels channels);
|
||||||
|
|
||||||
virtual AUD_Specs getSpecs() const;
|
virtual AUD_Specs getSpecs() const;
|
||||||
virtual void read(int& length, bool& eos, sample_t* buffer);
|
virtual void read(int& length, bool& eos, sample_t* buffer);
|
||||||
};
|
};
|
||||||
|
@@ -73,6 +73,11 @@ AUD_DeviceSpecs AUD_Mixer::getSpecs() const
|
|||||||
return m_specs;
|
return m_specs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AUD_Mixer::setSpecs(AUD_Specs specs)
|
||||||
|
{
|
||||||
|
m_specs.specs = specs;
|
||||||
|
}
|
||||||
|
|
||||||
void AUD_Mixer::clear(int length)
|
void AUD_Mixer::clear(int length)
|
||||||
{
|
{
|
||||||
m_buffer.assureSize(length * m_specs.channels * AUD_SAMPLE_SIZE(m_specs));
|
m_buffer.assureSize(length * m_specs.channels * AUD_SAMPLE_SIZE(m_specs));
|
||||||
|
@@ -47,7 +47,7 @@ protected:
|
|||||||
/**
|
/**
|
||||||
* The output specification.
|
* The output specification.
|
||||||
*/
|
*/
|
||||||
const AUD_DeviceSpecs m_specs;
|
AUD_DeviceSpecs m_specs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The length of the mixing buffer.
|
* The length of the mixing buffer.
|
||||||
@@ -81,6 +81,12 @@ public:
|
|||||||
*/
|
*/
|
||||||
AUD_DeviceSpecs getSpecs() const;
|
AUD_DeviceSpecs getSpecs() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the target specification for superposing.
|
||||||
|
* \param specs The target specification.
|
||||||
|
*/
|
||||||
|
void setSpecs(AUD_Specs specs);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mixes a buffer.
|
* Mixes a buffer.
|
||||||
* \param buffer The buffer to superpose.
|
* \param buffer The buffer to superpose.
|
||||||
|
@@ -48,9 +48,12 @@ AUD_SequencerFactory::~AUD_SequencerFactory()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void AUD_SequencerFactory::setThis(AUD_Reference<AUD_SequencerFactory>* self)
|
void AUD_SequencerFactory::setSpecs(AUD_Specs specs)
|
||||||
{
|
{
|
||||||
m_this = self;
|
m_specs = specs;
|
||||||
|
|
||||||
|
for(AUD_ReaderIterator i = m_readers.begin(); i != m_readers.end(); i++)
|
||||||
|
(*i)->setSpecs(m_specs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AUD_SequencerFactory::mute(bool muted)
|
void AUD_SequencerFactory::mute(bool muted)
|
||||||
@@ -103,7 +106,7 @@ void AUD_SequencerFactory::mute(AUD_Reference<AUD_SequencerEntry> entry, bool mu
|
|||||||
|
|
||||||
AUD_Reference<AUD_IReader> AUD_SequencerFactory::createReader()
|
AUD_Reference<AUD_IReader> AUD_SequencerFactory::createReader()
|
||||||
{
|
{
|
||||||
AUD_Reference<AUD_SequencerReader> reader = new AUD_SequencerReader(*m_this, m_entries,
|
AUD_Reference<AUD_SequencerReader> reader = new AUD_SequencerReader(this, m_entries,
|
||||||
m_specs, m_data,
|
m_specs, m_data,
|
||||||
m_volume);
|
m_volume);
|
||||||
m_readers.push_front(reader);
|
m_readers.push_front(reader);
|
||||||
|
@@ -66,7 +66,6 @@ private:
|
|||||||
bool m_muted;
|
bool m_muted;
|
||||||
void* m_data;
|
void* m_data;
|
||||||
AUD_volumeFunction m_volume;
|
AUD_volumeFunction m_volume;
|
||||||
AUD_Reference<AUD_SequencerFactory>* m_this;
|
|
||||||
|
|
||||||
// hide copy constructor and operator=
|
// hide copy constructor and operator=
|
||||||
AUD_SequencerFactory(const AUD_SequencerFactory&);
|
AUD_SequencerFactory(const AUD_SequencerFactory&);
|
||||||
@@ -76,7 +75,7 @@ public:
|
|||||||
AUD_SequencerFactory(AUD_Specs specs, bool muted, void* data, AUD_volumeFunction volume);
|
AUD_SequencerFactory(AUD_Specs specs, bool muted, void* data, AUD_volumeFunction volume);
|
||||||
~AUD_SequencerFactory();
|
~AUD_SequencerFactory();
|
||||||
|
|
||||||
void setThis(AUD_Reference<AUD_SequencerFactory>* self);
|
void setSpecs(AUD_Specs specs);
|
||||||
|
|
||||||
void mute(bool muted);
|
void mute(bool muted);
|
||||||
bool getMute() const;
|
bool getMute() const;
|
||||||
|
@@ -95,6 +95,22 @@ void AUD_SequencerReader::remove(AUD_Reference<AUD_SequencerEntry> entry)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AUD_SequencerReader::setSpecs(AUD_Specs specs)
|
||||||
|
{
|
||||||
|
m_mixer->setSpecs(specs);
|
||||||
|
|
||||||
|
AUD_Reference<AUD_SequencerStrip> strip;
|
||||||
|
for(AUD_StripIterator i = m_strips.begin(); i != m_strips.end(); i++)
|
||||||
|
{
|
||||||
|
strip = *i;
|
||||||
|
if(!strip->mapper.isNull())
|
||||||
|
{
|
||||||
|
strip->mapper->setChannels(specs.channels);
|
||||||
|
strip->resampler->setRate(specs.rate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool AUD_SequencerReader::isSeekable() const
|
bool AUD_SequencerReader::isSeekable() const
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
@@ -149,24 +165,30 @@ void AUD_SequencerReader::read(int& length, bool& eos, sample_t* buffer)
|
|||||||
strip->reader = (*strip->old_sound)->createReader();
|
strip->reader = (*strip->old_sound)->createReader();
|
||||||
// resample
|
// resample
|
||||||
#ifdef WITH_SAMPLERATE
|
#ifdef WITH_SAMPLERATE
|
||||||
strip->reader = new AUD_SRCResampleReader(strip->reader, m_mixer->getSpecs().specs);
|
strip->resampler = new AUD_SRCResampleReader(strip->reader, m_mixer->getSpecs().specs);
|
||||||
#else
|
#else
|
||||||
strip->reader = new AUD_LinearResampleReader(strip->reader, m_mixer->getSpecs().specs);
|
strip->resampler = new AUD_LinearResampleReader(strip->reader, m_mixer->getSpecs().specs);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// rechannel
|
// rechannel
|
||||||
strip->reader = new AUD_ChannelMapperReader(strip->reader, m_mixer->getSpecs().channels);
|
strip->mapper = new AUD_ChannelMapperReader(AUD_Reference<AUD_IReader>(strip->resampler), m_mixer->getSpecs().channels);
|
||||||
}
|
}
|
||||||
catch(AUD_Exception)
|
catch(AUD_Exception)
|
||||||
{
|
{
|
||||||
strip->reader = NULL;
|
strip->reader = NULL;
|
||||||
|
strip->resampler = NULL;
|
||||||
|
strip->mapper = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
strip->reader = NULL;
|
strip->reader = NULL;
|
||||||
|
strip->resampler = NULL;
|
||||||
|
strip->mapper = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!strip->reader.isNull())
|
if(!strip->mapper.isNull())
|
||||||
{
|
{
|
||||||
end = floor(strip->entry->end * rate);
|
end = floor(strip->entry->end * rate);
|
||||||
if(m_position < end)
|
if(m_position < end)
|
||||||
@@ -185,9 +207,9 @@ void AUD_SequencerReader::read(int& length, bool& eos, sample_t* buffer)
|
|||||||
current += strip->entry->skip * rate;
|
current += strip->entry->skip * rate;
|
||||||
len = length > end - m_position ? end - m_position : length;
|
len = length > end - m_position ? end - m_position : length;
|
||||||
len -= skip;
|
len -= skip;
|
||||||
if(strip->reader->getPosition() != current)
|
if(strip->mapper->getPosition() != current)
|
||||||
strip->reader->seek(current);
|
strip->mapper->seek(current);
|
||||||
strip->reader->read(len, eos, m_buffer.getBuffer());
|
strip->mapper->read(len, eos, m_buffer.getBuffer());
|
||||||
m_mixer->mix(m_buffer.getBuffer(), skip, len, m_volume(m_data, strip->entry->data, (float)m_position / (float)rate));
|
m_mixer->mix(m_buffer.getBuffer(), skip, len, m_volume(m_data, strip->entry->data, (float)m_position / (float)rate));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -35,11 +35,15 @@
|
|||||||
#include "AUD_IReader.h"
|
#include "AUD_IReader.h"
|
||||||
#include "AUD_SequencerFactory.h"
|
#include "AUD_SequencerFactory.h"
|
||||||
#include "AUD_Buffer.h"
|
#include "AUD_Buffer.h"
|
||||||
class AUD_Mixer;
|
#include "AUD_Mixer.h"
|
||||||
|
#include "AUD_ResampleReader.h"
|
||||||
|
#include "AUD_ChannelMapperReader.h"
|
||||||
|
|
||||||
struct AUD_SequencerStrip
|
struct AUD_SequencerStrip
|
||||||
{
|
{
|
||||||
AUD_Reference<AUD_IReader> reader;
|
AUD_Reference<AUD_IReader> reader;
|
||||||
|
AUD_Reference<AUD_ResampleReader> resampler;
|
||||||
|
AUD_Reference<AUD_ChannelMapperReader> mapper;
|
||||||
AUD_Reference<AUD_SequencerEntry> entry;
|
AUD_Reference<AUD_SequencerEntry> entry;
|
||||||
AUD_Reference<AUD_IFactory>* old_sound;
|
AUD_Reference<AUD_IFactory>* old_sound;
|
||||||
};
|
};
|
||||||
@@ -94,6 +98,7 @@ public:
|
|||||||
|
|
||||||
void add(AUD_Reference<AUD_SequencerEntry> entry);
|
void add(AUD_Reference<AUD_SequencerEntry> entry);
|
||||||
void remove(AUD_Reference<AUD_SequencerEntry> entry);
|
void remove(AUD_Reference<AUD_SequencerEntry> entry);
|
||||||
|
void setSpecs(AUD_Specs specs);
|
||||||
|
|
||||||
virtual bool isSeekable() const;
|
virtual bool isSeekable() const;
|
||||||
virtual void seek(int position);
|
virtual void seek(int position);
|
||||||
|
@@ -11,3 +11,4 @@ else:
|
|||||||
|
|
||||||
bpy.context.scene.render.ffmpeg_audio_mixrate = 48000
|
bpy.context.scene.render.ffmpeg_audio_mixrate = 48000
|
||||||
bpy.context.scene.render.ffmpeg_audio_codec = "PCM"
|
bpy.context.scene.render.ffmpeg_audio_codec = "PCM"
|
||||||
|
bpy.context.scene.render.ffmpeg_audio_channels = 2
|
||||||
|
@@ -21,3 +21,4 @@ bpy.context.scene.render.ffmpeg_muxrate = 10080000
|
|||||||
bpy.context.scene.render.ffmpeg_audio_codec = "AC3"
|
bpy.context.scene.render.ffmpeg_audio_codec = "AC3"
|
||||||
bpy.context.scene.render.ffmpeg_audio_bitrate = 448
|
bpy.context.scene.render.ffmpeg_audio_bitrate = 448
|
||||||
bpy.context.scene.render.ffmpeg_audio_mixrate = 48000
|
bpy.context.scene.render.ffmpeg_audio_mixrate = 48000
|
||||||
|
bpy.context.scene.render.ffmpeg_audio_channels = 6
|
||||||
|
@@ -21,3 +21,4 @@ bpy.context.scene.render.ffmpeg_muxrate = 0
|
|||||||
bpy.context.scene.render.ffmpeg_audio_bitrate = 224
|
bpy.context.scene.render.ffmpeg_audio_bitrate = 224
|
||||||
bpy.context.scene.render.ffmpeg_audio_mixrate = 44100
|
bpy.context.scene.render.ffmpeg_audio_mixrate = 44100
|
||||||
bpy.context.scene.render.ffmpeg_audio_codec = "MP2"
|
bpy.context.scene.render.ffmpeg_audio_codec = "MP2"
|
||||||
|
bpy.context.scene.render.ffmpeg_audio_channels = 2
|
||||||
|
@@ -21,3 +21,4 @@ bpy.context.scene.render.ffmpeg_muxrate = 2352 * 75 * 8
|
|||||||
bpy.context.scene.render.ffmpeg_audio_bitrate = 224
|
bpy.context.scene.render.ffmpeg_audio_bitrate = 224
|
||||||
bpy.context.scene.render.ffmpeg_audio_mixrate = 44100
|
bpy.context.scene.render.ffmpeg_audio_mixrate = 44100
|
||||||
bpy.context.scene.render.ffmpeg_audio_codec = "MP2"
|
bpy.context.scene.render.ffmpeg_audio_codec = "MP2"
|
||||||
|
bpy.context.scene.render.ffmpeg_audio_channels = 2
|
||||||
|
@@ -596,7 +596,9 @@ class RENDER_PT_encoding(RenderButtonsPanel, bpy.types.Panel):
|
|||||||
col.prop(rd, "ffmpeg_audio_bitrate")
|
col.prop(rd, "ffmpeg_audio_bitrate")
|
||||||
col.prop(rd, "ffmpeg_audio_mixrate")
|
col.prop(rd, "ffmpeg_audio_mixrate")
|
||||||
|
|
||||||
split.prop(rd, "ffmpeg_audio_volume", slider=True)
|
col = split.column()
|
||||||
|
col.prop(rd, "ffmpeg_audio_volume", slider=True)
|
||||||
|
col.prop(rd, "ffmpeg_audio_channels")
|
||||||
|
|
||||||
|
|
||||||
class RENDER_PT_bake(RenderButtonsPanel, bpy.types.Panel):
|
class RENDER_PT_bake(RenderButtonsPanel, bpy.types.Panel):
|
||||||
|
@@ -469,6 +469,7 @@ Scene *add_scene(const char *name)
|
|||||||
sce->r.ffcodecdata.audio_mixrate = 44100;
|
sce->r.ffcodecdata.audio_mixrate = 44100;
|
||||||
sce->r.ffcodecdata.audio_volume = 1.0f;
|
sce->r.ffcodecdata.audio_volume = 1.0f;
|
||||||
sce->r.ffcodecdata.audio_bitrate = 192;
|
sce->r.ffcodecdata.audio_bitrate = 192;
|
||||||
|
sce->r.ffcodecdata.audio_channels = 2;
|
||||||
|
|
||||||
BLI_strncpy(sce->r.engine, "BLENDER_RENDER", sizeof(sce->r.engine));
|
BLI_strncpy(sce->r.engine, "BLENDER_RENDER", sizeof(sce->r.engine));
|
||||||
|
|
||||||
|
@@ -346,6 +346,7 @@ AUD_Device* sound_mixdown(struct Scene *scene, AUD_DeviceSpecs specs, int start,
|
|||||||
|
|
||||||
AUD_setDeviceVolume(mixdown, volume);
|
AUD_setDeviceVolume(mixdown, volume);
|
||||||
|
|
||||||
|
AUD_setSequencerSpecs(scene->sound_scene, specs.specs);
|
||||||
AUD_freeHandle(AUD_playDevice(mixdown, scene->sound_scene, start / FPS));
|
AUD_freeHandle(AUD_playDevice(mixdown, scene->sound_scene, start / FPS));
|
||||||
|
|
||||||
return mixdown;
|
return mixdown;
|
||||||
@@ -405,6 +406,9 @@ static void sound_start_play_scene(struct Scene *scene)
|
|||||||
{
|
{
|
||||||
if(scene->sound_scene_handle)
|
if(scene->sound_scene_handle)
|
||||||
AUD_stop(scene->sound_scene_handle);
|
AUD_stop(scene->sound_scene_handle);
|
||||||
|
|
||||||
|
AUD_setSequencerDeviceSpecs(scene->sound_scene);
|
||||||
|
|
||||||
if((scene->sound_scene_handle = AUD_play(scene->sound_scene, 1)))
|
if((scene->sound_scene_handle = AUD_play(scene->sound_scene, 1)))
|
||||||
AUD_setLoop(scene->sound_scene_handle, -1);
|
AUD_setLoop(scene->sound_scene_handle, -1);
|
||||||
}
|
}
|
||||||
|
@@ -549,7 +549,7 @@ static AVStream* alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex
|
|||||||
c->sample_rate = rd->ffcodecdata.audio_mixrate;
|
c->sample_rate = rd->ffcodecdata.audio_mixrate;
|
||||||
c->bit_rate = ffmpeg_audio_bitrate*1000;
|
c->bit_rate = ffmpeg_audio_bitrate*1000;
|
||||||
c->sample_fmt = SAMPLE_FMT_S16;
|
c->sample_fmt = SAMPLE_FMT_S16;
|
||||||
c->channels = 2;
|
c->channels = rd->ffcodecdata.audio_channels;
|
||||||
codec = avcodec_find_encoder(c->codec_id);
|
codec = avcodec_find_encoder(c->codec_id);
|
||||||
if (!codec) {
|
if (!codec) {
|
||||||
//XXX error("Couldn't find a valid audio codec");
|
//XXX error("Couldn't find a valid audio codec");
|
||||||
@@ -574,12 +574,11 @@ static AVStream* alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex
|
|||||||
audio_outbuf_size = c->frame_size * c->channels * sizeof(int16_t) * 4;
|
audio_outbuf_size = c->frame_size * c->channels * sizeof(int16_t) * 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
audio_output_buffer = (uint8_t*)MEM_mallocN(
|
audio_output_buffer = (uint8_t*)av_malloc(
|
||||||
audio_outbuf_size, "FFMPEG audio encoder input buffer");
|
audio_outbuf_size);
|
||||||
|
|
||||||
audio_input_buffer = (uint8_t*)MEM_mallocN(
|
audio_input_buffer = (uint8_t*)av_malloc(
|
||||||
audio_input_samples * c->channels * sizeof(int16_t),
|
audio_input_samples * c->channels * sizeof(int16_t));
|
||||||
"FFMPEG audio encoder output buffer");
|
|
||||||
|
|
||||||
audio_time = 0.0f;
|
audio_time = 0.0f;
|
||||||
|
|
||||||
@@ -701,7 +700,7 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report
|
|||||||
|
|
||||||
if (ffmpeg_type == FFMPEG_DV) {
|
if (ffmpeg_type == FFMPEG_DV) {
|
||||||
fmt->audio_codec = CODEC_ID_PCM_S16LE;
|
fmt->audio_codec = CODEC_ID_PCM_S16LE;
|
||||||
if (ffmpeg_audio_codec != CODEC_ID_NONE && rd->ffcodecdata.audio_mixrate != 48000) {
|
if (ffmpeg_audio_codec != CODEC_ID_NONE && rd->ffcodecdata.audio_mixrate != 48000 && rd->ffcodecdata.audio_channels != 2) {
|
||||||
BKE_report(reports, RPT_ERROR, "FFMPEG only supports 48khz / stereo audio for DV!");
|
BKE_report(reports, RPT_ERROR, "FFMPEG only supports 48khz / stereo audio for DV!");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -971,11 +970,11 @@ void end_ffmpeg(void)
|
|||||||
video_buffer = 0;
|
video_buffer = 0;
|
||||||
}
|
}
|
||||||
if (audio_output_buffer) {
|
if (audio_output_buffer) {
|
||||||
MEM_freeN(audio_output_buffer);
|
av_free(audio_output_buffer);
|
||||||
audio_output_buffer = 0;
|
audio_output_buffer = 0;
|
||||||
}
|
}
|
||||||
if (audio_input_buffer) {
|
if (audio_input_buffer) {
|
||||||
MEM_freeN(audio_input_buffer);
|
av_free(audio_input_buffer);
|
||||||
audio_input_buffer = 0;
|
audio_input_buffer = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -11474,6 +11474,12 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
|
|||||||
kb->slidermax = kb->slidermin + 1.0f;
|
kb->slidermax = kb->slidermin + 1.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
Scene *scene;
|
||||||
|
for (scene=main->scene.first; scene; scene=scene->id.next)
|
||||||
|
scene->r.ffcodecdata.audio_channels = 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (main->versionfile < 256 || (main->versionfile == 256 && main->subversionfile < 1)) {
|
if (main->versionfile < 256 || (main->versionfile == 256 && main->subversionfile < 1)) {
|
||||||
|
@@ -126,6 +126,8 @@ typedef struct FFMpegCodecData {
|
|||||||
int video_bitrate;
|
int video_bitrate;
|
||||||
int audio_bitrate;
|
int audio_bitrate;
|
||||||
int audio_mixrate;
|
int audio_mixrate;
|
||||||
|
int audio_channels;
|
||||||
|
int audio_pad;
|
||||||
float audio_volume;
|
float audio_volume;
|
||||||
int gop_size;
|
int gop_size;
|
||||||
int flags;
|
int flags;
|
||||||
|
@@ -98,6 +98,14 @@ EnumPropertyItem snap_element_items[] = {
|
|||||||
{SCE_SNAP_MODE_VOLUME, "VOLUME", ICON_SNAP_VOLUME, "Volume", "Snap to volume"},
|
{SCE_SNAP_MODE_VOLUME, "VOLUME", ICON_SNAP_VOLUME, "Volume", "Snap to volume"},
|
||||||
{0, NULL, 0, NULL, NULL}};
|
{0, NULL, 0, NULL, NULL}};
|
||||||
|
|
||||||
|
static EnumPropertyItem audio_channel_items[] = {
|
||||||
|
{1, "MONO", 0, "Mono", "Set audio channels to mono"},
|
||||||
|
{2, "STEREO", 0, "Stereo", "Set audio channels to stereo"},
|
||||||
|
{4, "SURROUND4", 0, "4 Channels", "Set audio channels to 4 channels"},
|
||||||
|
{6, "SURROUND51", 0, "5.1 Surround", "Set audio channels to 5.1 surround sound"},
|
||||||
|
{8, "SURROUND71", 0, "7.1 Surround", "Set audio channels to 7.1 surround sound"},
|
||||||
|
{0, NULL, 0, NULL, NULL}};
|
||||||
|
|
||||||
EnumPropertyItem image_type_items[] = {
|
EnumPropertyItem image_type_items[] = {
|
||||||
{0, "", 0, "Image", NULL},
|
{0, "", 0, "Image", NULL},
|
||||||
{R_BMP, "BMP", ICON_FILE_IMAGE, "BMP", "Output image in bitmap format"},
|
{R_BMP, "BMP", ICON_FILE_IMAGE, "BMP", "Output image in bitmap format"},
|
||||||
@@ -2468,6 +2476,10 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
|
|||||||
RNA_def_property_ui_text(prop, "Volume", "Audio volume");
|
RNA_def_property_ui_text(prop, "Volume", "Audio volume");
|
||||||
RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
|
RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
|
||||||
|
|
||||||
|
prop= RNA_def_property(srna, "ffmpeg_audio_channels", PROP_ENUM, PROP_NONE);
|
||||||
|
RNA_def_property_enum_sdna(prop, NULL, "ffcodecdata.audio_channels");
|
||||||
|
RNA_def_property_enum_items(prop, audio_channel_items);
|
||||||
|
RNA_def_property_ui_text(prop, "Audio Channels", "Sets the audio channel count");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
prop= RNA_def_property(srna, "fps", PROP_INT, PROP_NONE);
|
prop= RNA_def_property(srna, "fps", PROP_INT, PROP_NONE);
|
||||||
|
Reference in New Issue
Block a user