diff options
Diffstat (limited to 'Src/Agave/Encode')
-rw-r--r-- | Src/Agave/Encode/ifc_audioFileEncoder.h | 60 | ||||
-rw-r--r-- | Src/Agave/Encode/notes.txt | 23 | ||||
-rw-r--r-- | Src/Agave/Encode/svc_audioFileEncoder.h | 64 |
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 |