Filter SDK/Getting started with audio

From Avisynth wiki
(Difference between revisions)
Jump to: navigation, search
 
(5 intermediate revisions by one user not shown)
Line 6: Line 6:
  
 
  AVSValue __cdecl HalfVolume::Create(AVSValue args, void*, IScriptEnvironment* env) {
 
  AVSValue __cdecl HalfVolume::Create(AVSValue args, void*, IScriptEnvironment* env) {
   if (!args[0].AsClip()->GetVideoInfo().AudioChannels())
+
   if (!args[0].AsClip()->GetVideoInfo().HasAudio())
 
     return args[0];
 
     return args[0];
 
   
 
   
  return new HalfVolume(args[0].AsClip());
+
  // Auto convert audio to a compatible format.
 +
  AVSValue CA_args[3] = { args[0], SAMPLE_INT16 | SAMPLE_FLOAT, SAMPLE_FLOAT };
 +
  PClip clip = env->Invoke("ConvertAudio", AVSValue(CA_args, 3)).AsClip();
 +
 +
  return new HalfVolume(clip);
 
  }
 
  }
 +
 +
What ConvertAudio() does is, that you tell it that your filter supports SAMPLE_INT16 and SAMPLE_FLOAT, and that it prefers SAMPLE_FLOAT. If the input isn't 16 bit or float, it'll be converted to float, otherwise the original PClip is returned.
  
 
'''Constructor:'''
 
'''Constructor:'''
Line 17: Line 23:
 
     : GenericVideoFilter(ConvertAudio::Create(_child, SAMPLE_INT16 | SAMPLE_FLOAT, SAMPLE_FLOAT)) {   
 
     : GenericVideoFilter(ConvertAudio::Create(_child, SAMPLE_INT16 | SAMPLE_FLOAT, SAMPLE_FLOAT)) {   
 
  }
 
  }
 
This is a bit tricky. It'll require you to include [http://avisynth2.cvs.sourceforge.net/avisynth2/avisynth/src/audio/convertaudio.cpp?view=markup convertaudio.cpp]. What it does is automatic sample type conversion. Basically what it does is that you tell that your filter ''supports'' SAMPLE_INT16 and SAMPLE_FLOAT, and that it ''prefers'' SAMPLE_FLOAT. If the input isn't 16 bit or float, it'll be converted to float.
 
  
 
'''GetAudio override:'''
 
'''GetAudio override:'''
Line 45: Line 49:
 
Implementation of a half volume filter. Very explicit, so it isn't going to be the fastest possible, but it should serve the purpose. Furthermore have a look [http://forum.doom9.org/showthread.php?s=&threadid=72760&highlight=ConvertAudio here] and look also at [http://avisynth2.cvs.sourceforge.net/avisynth2/avisynth/src/audio/audio.cpp?view=markup audio.cpp] for a bunch of more advanced stuff. A lot of technical details are also to be found in AviSynth [[Filter_SDK/Two-Five_Audio|Two-Five Audio]].
 
Implementation of a half volume filter. Very explicit, so it isn't going to be the fastest possible, but it should serve the purpose. Furthermore have a look [http://forum.doom9.org/showthread.php?s=&threadid=72760&highlight=ConvertAudio here] and look also at [http://avisynth2.cvs.sourceforge.net/avisynth2/avisynth/src/audio/audio.cpp?view=markup audio.cpp] for a bunch of more advanced stuff. A lot of technical details are also to be found in AviSynth [[Filter_SDK/Two-Five_Audio|Two-Five Audio]].
  
Back to [[Filter_SDK|Filter SDK]].
+
----
 +
 
 +
Since we are invoking ConvertAudio() you might wonder whether it is possible to call it in a script. That is indeed possible, but not documented since it is not very practical to do so. You need to know that SAMPLE_INT8 = 1b = 1, SAMPLE_INT16 = 10b = 2, SAMPLE_INT24 = 100b = 4, SAMPLE_INT32 = 1000b = 8 and SAMPLE_FLOAT = 10000b = 16 (although these values might change some day).
 +
 
 +
In the example above we call ConvertAudio() with SAMPLE_INT16 | SAMPLE_FLOAT = 10b | 10000b = 10010b = 18, so you need to call it as ConvertAudio(clip, 18, 16).
 +
 
 +
You should realise that float audio will be converted to 16 bit when feeding it to the encoder. At least unless you have set [[Internal_functions#OPT_AllowFloatAudio|global OPT_AllowFloatAudio = True]] in your script.
  
 
[[Category:FilterSDK]]
 
[[Category:FilterSDK]]

Latest revision as of 20:00, 7 June 2015

The best filters to take a look at if you are searching for a way to get started with an audio filter is the internal audio filters of AviSynth. Mainly audio.cpp is interesting.

Basically you override GetAudio(...) instead of GetFrame, and fill the buffer with data. A simple filter could look like this:

Filter creation - skip if no audio:

AVSValue __cdecl HalfVolume::Create(AVSValue args, void*, IScriptEnvironment* env) {
  if (!args[0].AsClip()->GetVideoInfo().HasAudio())
    return args[0];

  // Auto convert audio to a compatible format.
  AVSValue CA_args[3] = { args[0], SAMPLE_INT16 | SAMPLE_FLOAT, SAMPLE_FLOAT };
  PClip clip = env->Invoke("ConvertAudio", AVSValue(CA_args, 3)).AsClip();

  return new HalfVolume(clip);
}

What ConvertAudio() does is, that you tell it that your filter supports SAMPLE_INT16 and SAMPLE_FLOAT, and that it prefers SAMPLE_FLOAT. If the input isn't 16 bit or float, it'll be converted to float, otherwise the original PClip is returned.

Constructor:

HalfVolume::HalfVolume(PClip _child)
    : GenericVideoFilter(ConvertAudio::Create(_child, SAMPLE_INT16 | SAMPLE_FLOAT, SAMPLE_FLOAT)) {   
}

GetAudio override:

void __stdcall HalfVolume::GetAudio(void* buf, __int64 start, __int64 count, IScriptEnvironment* env) {
  child->GetAudio(buf, start, count, env);
  int channels = vi.AudioChannels();

  if (vi.SampleType() == SAMPLE_INT16) {
    short* samples = (short*)buf;
    for (int i=0; i<count; i++) {
      for(int j=0;j<channels;j++) {
         samples[i*channels+j] /= 2;
      }
    }
  } else if (vi.SampleType() == SAMPLE_FLOAT) {
    SFLOAT* samples = (SFLOAT*)buf;
    for (int i=0; i<count; i++) {
      for(int j=0;j<channels;j++) {
         samples[i*channels+j] /= 2.0f;
      }
    }
  }
}

Implementation of a half volume filter. Very explicit, so it isn't going to be the fastest possible, but it should serve the purpose. Furthermore have a look here and look also at audio.cpp for a bunch of more advanced stuff. A lot of technical details are also to be found in AviSynth Two-Five Audio.


Since we are invoking ConvertAudio() you might wonder whether it is possible to call it in a script. That is indeed possible, but not documented since it is not very practical to do so. You need to know that SAMPLE_INT8 = 1b = 1, SAMPLE_INT16 = 10b = 2, SAMPLE_INT24 = 100b = 4, SAMPLE_INT32 = 1000b = 8 and SAMPLE_FLOAT = 10000b = 16 (although these values might change some day).

In the example above we call ConvertAudio() with SAMPLE_INT16 | SAMPLE_FLOAT = 10b | 10000b = 10010b = 18, so you need to call it as ConvertAudio(clip, 18, 16).

You should realise that float audio will be converted to 16 bit when feeding it to the encoder. At least unless you have set global OPT_AllowFloatAudio = True in your script.

Personal tools