aboutsummaryrefslogtreecommitdiff
path: root/Src/Agave/Encode
diff options
context:
space:
mode:
Diffstat (limited to 'Src/Agave/Encode')
-rw-r--r--Src/Agave/Encode/ifc_audioFileEncoder.h60
-rw-r--r--Src/Agave/Encode/notes.txt23
-rw-r--r--Src/Agave/Encode/svc_audioFileEncoder.h64
3 files changed, 147 insertions, 0 deletions
diff --git a/Src/Agave/Encode/ifc_audioFileEncoder.h b/Src/Agave/Encode/ifc_audioFileEncoder.h
new file mode 100644
index 00000000..f0f7c3ce
--- /dev/null
+++ b/Src/Agave/Encode/ifc_audioFileEncoder.h
@@ -0,0 +1,60 @@
+#pragma once
+#include <bfc/dispatch.h>
+class ifc_audioFileEncoder : public Dispatchable
+{
+protected:
+ ifc_audioFileEncoder() {}
+ ~ifc_audioFileEncoder() {}
+public:
+ /*
+ @param frame - frame number, optional (pass 0 every time if you don't have it).
+ it is used for special purposes and is not generally needed.
+ @param data - the input data (audio)
+ @param data_len - number of valid bytes in data
+ @param data_used - on return, set to the number of audio bytes read
+
+ note for implementors:
+ it is highly recommended that implementation use all available input data, but it is not required.
+
+ note for users:
+ if not all input data is read, you need to pass in the old data again
+ but have more available. This is likely to happen when the block size of the codec
+ does not match your buffer size
+ */
+ int Feed(uint32_t frame, const void *data, size_t data_len, size_t *data_used);
+
+ // same as above, but used when you have no more input to pass
+ // you can pass more audio data if you like (preferred if possible)
+ // or pass 0 for data & data_len if you passed all your data to Feed()
+ // note to implementors:
+ // for many implementations: close your encoder (e.g. vorbis) but not your file writer (e.g. ogg)
+ // note to users:
+ // you still need to call Finish().
+ int Finish(uint32_t frame, const void *data, size_t data_len, size_t *data_used);
+
+ // call this to do whatever necessary
+ // this is a separate call than Finish() because of time-constraints and the killswitch
+ // for many implementations: close your file writer object here, write seek table, etc.
+ // note to users:
+ // after this function succeeds, you may use the file (write metadata, etc)
+ int Finalize(int *killswitch);
+
+ // @param block_size - on return, set to the 'natural' number of bytes that the audio encoder expects
+ // can be helpful for users of this object to do more efficient I/O
+ // optional (check the return value when you call this!)
+ // but recommended
+ int GetBlockSize(size_t *block_size);
+
+ // @param fill_size - on return, set to the number of bytes needed to fill the audio encoder's current block
+ // might be 0 for some types (WAV).
+ // can be helpful for users of this object to do more efficient I/O
+ // optional (check the return value when you call this!)
+ // don't implement unless it's easy
+ int GetFillSize(size_t *fill_size);
+
+ // @param bytes_written - on return, set to the number of encoded bytes written so far.
+ // used by the CD ripper to show a 'real time' bitrate
+ // optional (check the return value when you call this!)
+ // don't implement unless it's easy
+ int GetBytesWritten(size_t *bytes_written);
+}; \ No newline at end of file
diff --git a/Src/Agave/Encode/notes.txt b/Src/Agave/Encode/notes.txt
new file mode 100644
index 00000000..1bd767e6
--- /dev/null
+++ b/Src/Agave/Encode/notes.txt
@@ -0,0 +1,23 @@
+notes for encoders
+
+====
+two types of encoders:
+1) File encoders. These write directly to a file.
+2) Stream encoders. These return the encoded audio data in a user-provided buffer
+
+For example, an AAC encoder could implement a file encoder for MP4/M4A files, but these aren't streamable.
+ADTS AAC however, would be streamable.
+
+====
+Two ways of feeding the data
+1) Push model. The user of the class passes data in a user-owned data buffer.
+2) Pull model. The implementor of the class pulls data from a user-provided callback (data is stored in an implementor-owned buffer)
+
+Push encoders should be used when the incoming audio data is not immediately available (live recording, CD ripping).
+Pull encoders should only be used when all the audio data is immediately available (e.g. WAV file).
+
+When in doubt, use a push encoder. Pull encoders offer a potential advantage of better memory usage (fewer memcpy's in most implementations), but a push encoder should serve all needs.
+
+====
+Note that encoders should be as non-blocking as possible (except for, obviously, computation, file I/O and thread synchronization for multi-core-aware encoders).
+It it not reommended to Sleep(), select() [network I/O], etc. Stick to what the API was designed for :)
diff --git a/Src/Agave/Encode/svc_audioFileEncoder.h b/Src/Agave/Encode/svc_audioFileEncoder.h
new file mode 100644
index 00000000..7368a23b
--- /dev/null
+++ b/Src/Agave/Encode/svc_audioFileEncoder.h
@@ -0,0 +1,64 @@
+#pragma once
+/*
+Service for creating Audio Encoders which encode straight to a file.
+
+This interface is not meant to do the encoding itself, it is a factory to create and destroy
+encoder objects (ifc_audioFileEncoder)
+*/
+#include <bfc/dispatch.h>
+#include "ifc_audioFileEncoder.h"
+#include "../DecodeFile/api_decodefile.h" // for AudioParameters struct
+#include <bfc/std_mkncc.h> // for MKnCC()
+class svc_audioFileEncoder : public Dispatchable
+{
+protected:
+ svc_audioFileEncoder() {}
+ ~svc_audioFileEncoder() {}
+public:
+ static FOURCC getServiceType() { return svc_albumArtProvider::SERVICETYPE; }
+ /*
+ General parameter notes (for all methods of this class):
+ @param profile is a filename of an INI file where the encoder settings are stored
+ @param parameters defines the input audio data. For methods where this parameter
+ is optional (default parameter value == 0), it is meant to be passed to optionally
+ limit configuration choices. For example, an AAC encoder could hide surround-sound
+ encoding options when parameters->channels == 2
+ */
+
+ // return a user-friendly name for the encoder,
+ // e.g. "Nullsoft FLAC encoder v2.1"
+ const wchar_t *GetName();
+
+ // retrieve information about a particular profile
+ // @param profile_item information to retrieve. currently, there are only three defined strings
+ // "bitrate" -- retrieve an estimate bitrate (in kbps) for the profile
+ // "profile" -- retrieve a more specific name for a given profile (and optional input parameters)
+ // e.g. an AAC encoder could return "HE-AAC v2, 16kbps, MP4 File Format" or "AAC LC, ADTS stream"
+ // "settings" -- retrieve a string that codifies the settings in the profile
+ // for most codecs, this should mirror what the commandline string would be for the corresponding
+ // commandline codec (flac.exe, lame.exe, etc).
+ // e.g. "-V 2"
+ int GetProfileInfo(const wchar_t *profile, const wchar_t *profile_item, wchar_t *value, size_t value_cch, const AudioParameters *parameters = 0);
+
+ // not currently used for anything
+ int SetProfileInfo(const wchar_t *profile, const wchar_t *profile_item, const wchar_t *value, AudioParameters *parameters = 0);
+
+ // this function gets the party started. call after you have opened your input file (thru
+ // api_decodefile, for example) so you can pass in a valid parameters struct.
+ // @param filename destination filename
+ int Create(ifc_audioFileEncoder **encoder, const wchar_t *filename, const wchar_t *profile, const AudioParameters *parameters);
+
+ // call this when you are done
+ void Destroy(ifc_audioFileEncoder *encoder);
+
+ // if parent is NULL, pop up a modal dialog/window
+ // if parent is not NULL, return a modeless child dialog/window
+ HWND Configure(HWND parent, const wchar_t *profile, const AudioParameters *parameters = 0);
+
+
+ enum
+ {
+ SERVICETYPE = MK4CC('a','f','e', 'n')
+ };
+
+}; \ No newline at end of file