|
1
|
Media / Multimedia / Re: Unir video (mp4) + audio (mp4) "opus"
|
en: 1 Mayo 2024, 05:53 am
|
Lo estoy haciendo con avidemux, pero para ello primero tengo que pasar online la pista de audio mp4 "opus" a mp3, y busco uno que lo haga todo directamente. Como alternativa a FFMPEG, y solo en caso de que NO te resulte necesario preservar el formato de contenedor MP4: Lo único que necesitas para combinar una pista de audio OPUS en un contenedor de video MP4, es MKVToolnix. Es tan sencillo como cargar el archivo de video, arrastrar el archivo de audio para añadirlo al contenedor, y darle al botón "Iniciar multiplexado" para generar el nuevo video de forma lossless. Eso sí, el formato del nuevo contenedor será Matroska (MKV). - https://mkvtoolnix.download/downloads.html#windowsEste procedimiento de multiplexado lo puedes automatizar mediante el uso de mkvmerge.exe por línea de comandos, en caso de que lo necesitases. Un saludo.
|
|
|
2
|
Programación / .NET (C#, VB.NET, ASP) / Re: Librería de Snippets para VB.NET !! (Compartan aquí sus snippets)
|
en: 27 Abril 2024, 03:03 am
|
Comparto un enfoque y uso alternativo al código que he publicado arriba. Este enfoque nos permite atribuir nombres específicos a una enumeración para mostrarlos en un property grid. Modo de empleo: Imports System.Componentmodel <TypeConverter(GetType(EnumDescriptionConverter))> Public Enum TestEnum <Description("My Upper Camel Case Name")> MyUpperCamelCaseName = 1 <Description("My Lower Camel Case Name")> myLowerCamelCaseName = 2 <Description("My Upper Snake Case Name")> My_Upper_Snake_Case_Name = 3 <Description("My lower snake case Name")> my_lower_snake_case_Name = 4 <Description("My Mixed value 123 QWERTY 456 wtf_")> MyMixed_value123_QWERTY456wtf_ = 5 <Description("Rare case STRANGE Name 123 aZ Az 456")> ___rare_case_STRANGE_Name___________123_aZ_Az_4_5_6_ = 6 End Enum
<DefaultValue(TestEnum.MyUpperCamelCaseName)> Public Property Test As TestEnum = TestEnum.MyUpperCamelCaseName
El código: Imports System.ComponentModel Imports System.Globalization Imports System.Reflection Public NotInheritable Class EnumDescriptionConverter : Inherits EnumConverter ''' <summary> ''' Initializes a new instance of the <see cref="EnumDescriptionConverter"/> class. ''' </summary> ''' <param name="type">A <see cref="T:System.Type" /> that represents the type of enumeration to associate with this enumeration converter.</param> Public Sub New(type As Type) MyBase.New(type) End Sub ''' <summary> ''' Returns whether this converter can convert the object to the specified type, using the specified context. ''' </summary> ''' ''' <param name="context"> ''' An <see cref="ITypeDescriptorContext"/> that provides a format context. ''' </param> ''' ''' <param name="destinationType"> ''' A <see cref="Type"/> that represents the type you want to convert to. ''' </param> ''' ''' <returns> ''' <see langword="True"/> if this converter can perform the conversion; otherwise, <see langword="False"/>. ''' </returns> Public Overrides Function CanConvertTo(context As ITypeDescriptorContext, destinationType As Type) As Boolean Return destinationType Is GetType(String) OrElse MyBase.CanConvertTo(context, destinationType) End Function ''' <summary> ''' Returns whether this converter can convert an object of the given type to the type of this converter, ''' using the specified context. ''' </summary> ''' ''' <param name="context"> ''' An <see cref="ITypeDescriptorContext"/> that provides a format context. ''' </param> ''' ''' <param name="sourceType"> ''' A <see cref="Type" /> that represents the type you want to convert from. ''' </param> ''' ''' <returns> ''' <see langword="True"/> if this converter can perform the conversion; otherwise, <see langword="False"/>. ''' </returns> Public Overrides Function CanConvertFrom(context As ITypeDescriptorContext, sourceType As Type) As Boolean Return sourceType Is GetType(String) OrElse MyBase.CanConvertFrom(context, sourceType) End Function ''' <summary> ''' Converts the given value object to the specified type, using the specified context and culture information. ''' </summary> ''' ''' <param name="context"> ''' An <see cref="ITypeDescriptorContext"/> that provides a format context. ''' </param> ''' ''' <param name="culture"> ''' A <see cref="CultureInfo"/>. If null is passed, the current culture is assumed. ''' </param> ''' ''' <param name="value"> ''' The <see cref="Object"/> to convert. ''' </param> ''' ''' <param name="destinationType"> ''' The <see cref="Type"/> to convert the <paramref name="value"/> parameter to. ''' </param> ''' ''' <returns> ''' An <see cref="Object"/> that represents the converted value. ''' </returns> <DebuggerStepThrough> Public Overrides Function ConvertTo(context As ITypeDescriptorContext, culture As CultureInfo, value As Object, destinationType As Type) As Object Dim fi As FieldInfo = Me.EnumType.GetField([Enum].GetName(Me.EnumType, value)) Dim dna As DescriptionAttribute = CType(Attribute.GetCustomAttribute(fi, GetType(DescriptionAttribute)), DescriptionAttribute) Return If(dna IsNot Nothing, dna.Description, value.ToString()) End Function ''' <summary> ''' Converts the given object to the type of this converter, using the specified context and culture information. ''' </summary> ''' ''' <param name="context"> ''' An <see cref="ITypeDescriptorContext"/> that provides a format context. ''' </param> ''' ''' <param name="culture"> ''' The <see cref="CultureInfo"/> to use as the current culture. ''' </param> ''' ''' <param name="value"> ''' The <see cref="Object"/> to convert. ''' </param> ''' ''' <returns> ''' An <see cref="Object"/> that represents the converted value. ''' </returns> <DebuggerStepThrough> Public Overrides Function ConvertFrom(context As ITypeDescriptorContext, culture As CultureInfo, value As Object) As Object For Each fi As FieldInfo In Me.EnumType.GetFields() Dim dna As DescriptionAttribute = CType(Attribute.GetCustomAttribute(fi, GetType(DescriptionAttribute)), DescriptionAttribute) If (dna IsNot Nothing) AndAlso DirectCast(value, String) = dna.Description Then Return [Enum].Parse(Me.EnumType, fi.Name, ignoreCase:=False) End If Next fi Return [Enum].Parse(Me.EnumType, DirectCast(value, String)) End Function End Class
|
|
|
3
|
Programación / .NET (C#, VB.NET, ASP) / Re: Librería de Snippets para VB.NET !! (Compartan aquí sus snippets)
|
en: 27 Abril 2024, 01:20 am
|
Comparto otro type converter, para convertir los nombres de los valores de una Enum, a una representación amistosa para mostrarlos, por ejemplo, en un propertygrid. Este convertidor está optimizado para nombres de enumeración escritos en upper/lower snake case y upper/lower camel case. Las palabras se separan con un espacio en blanco convencional, y los guiones bajos se reemplazan por un espacio en blanco unicode. Ejemplo de uso: <TypeConverter(GetType(EnumNameFormatterConverter))> Public Enum TestEnum MyUpperCamelCaseName myLowerCamelCaseName My_Upper_Snake_Case_Name my_lower_snake_case_name MyMixed_value123_WTF456wtf_ ___rare_case_STRANGE_Name___________123_aZ_Az_4_5_6_ End Enum
<DefaultValue(TestEnum.MyUpperCamelCaseName)> Public Property Test As TestEnum = TestEnum.MyUpperCamelCaseName
Sin formato: Con formato: El código:EnumNameFormatterConverter.vb Imports System.ComponentModel Imports System.Globalization Imports System.Runtime.InteropServices Imports System.Text ''' <summary> ''' Provides conversion functionality between the value names of an <see cref="[Enum]"/> to a friendly string representation. ''' <para></para> ''' This converter is optimized for enum names written in either upper/lower snake case or upper/lower camel case: ''' <list type="bullet"> ''' <item><description>Snake case: Each word is separated by underscores (e.g.: "My_Value").</description></item> ''' <item><description>Camel case: Each word is separated by a capitalized letter (e.g.: "MyValue").</description></item> ''' </list> ''' </summary> Public NotInheritable Class EnumNameFormatterConverter : Inherits EnumConverter ''' <summary> ''' Initializes a new instance of the <see cref="EnumNameFormatterConverter"/> class. ''' </summary> ''' <param name="type">A <see cref="T:System.Type" /> that represents the type of enumeration to associate with this enumeration converter.</param> Public Sub New(type As Type) MyBase.New(type) End Sub ''' <summary> ''' Returns whether this converter can convert an object of the given type to the type of this converter, ''' using the specified context. ''' </summary> ''' ''' <param name="context"> ''' An <see cref="ITypeDescriptorContext"/> that provides a format context. ''' </param> ''' ''' <param name="sourceType"> ''' A <see cref="Type" /> that represents the type you want to convert from. ''' </param> ''' ''' <returns> ''' <see langword="True"/> if this converter can perform the conversion; otherwise, <see langword="False"/>. ''' </returns> Public Overrides Function CanConvertFrom(context As ITypeDescriptorContext, sourceType As Type) As Boolean Return sourceType Is GetType(String) OrElse MyBase.CanConvertFrom(context, sourceType) End Function ''' <summary> ''' Returns whether this converter can convert the object to the specified type, using the specified context. ''' </summary> ''' ''' <param name="context"> ''' An <see cref="ITypeDescriptorContext"/> that provides a format context. ''' </param> ''' ''' <param name="destinationType"> ''' A <see cref="Type"/> that represents the type you want to convert to. ''' </param> ''' ''' <returns> ''' <see langword="True"/> if this converter can perform the conversion; otherwise, <see langword="False"/>. ''' </returns> Public Overrides Function CanConvertTo(context As ITypeDescriptorContext, destinationType As Type) As Boolean Return destinationType Is GetType(String) OrElse MyBase.CanConvertTo(context, destinationType) End Function ''' <summary> ''' Converts the given object to the type of this converter, using the specified context and culture information. ''' </summary> ''' ''' <param name="context"> ''' An <see cref="ITypeDescriptorContext"/> that provides a format context. ''' </param> ''' ''' <param name="culture"> ''' The <see cref="CultureInfo"/> to use as the current culture. ''' </param> ''' ''' <param name="value"> ''' The <see cref="Object"/> to convert. ''' </param> ''' ''' <returns> ''' An <see cref="Object"/> that represents the converted value. ''' </returns> <DebuggerStepThrough> Public Overrides Function ConvertFrom(context As ITypeDescriptorContext, culture As CultureInfo, value As Object) As Object If TypeOf value Is String Then value = DirectCast(value, String).Replace(" ", "").Replace(Convert.ToChar(&H205F), "_"c) Return [Enum].Parse(Me.EnumType, value, ignoreCase:=True) End If Return MyBase.ConvertFrom(context, culture, value) End Function ''' <summary> ''' Converts the given value object to the specified type, using the specified context and culture information. ''' </summary> ''' ''' <param name="context"> ''' An <see cref="ITypeDescriptorContext"/> that provides a format context. ''' </param> ''' ''' <param name="culture"> ''' A <see cref="CultureInfo"/>. If null is passed, the current culture is assumed. ''' </param> ''' ''' <param name="value"> ''' The <see cref="Object"/> to convert. ''' </param> ''' ''' <param name="destinationType"> ''' The <see cref="Type"/> to convert the <paramref name="value"/> parameter to. ''' </param> ''' ''' <returns> ''' An <see cref="Object"/> that represents the converted value. ''' </returns> <DebuggerStepThrough> Public Overrides Function ConvertTo(context As ITypeDescriptorContext, culture As CultureInfo, value As Object, destinationType As Type) As Object If destinationType = GetType(String) Then Dim name As String = [Enum].GetName(value.GetType(), value) If Not String.IsNullOrEmpty(name) Then Return Me.FormatName(name) End If End If Return MyBase.ConvertTo(context, culture, value, destinationType) End Function ''' <summary> ''' Formats the name of a <see cref="[Enum]"/> value to a friendly name. ''' </summary> ''' ''' <param name="name"> ''' <see cref="[Enum]"/> value name. ''' </param> ''' ''' <returns> ''' The resulting friendly name. ''' </returns> <DebuggerStepThrough> Private Function FormatName(name As String) As String Dim sb As New StringBuilder() Dim previousChar As Char Dim previousCharIsWhiteSpace As Boolean Dim previousCharIsUpperLetter As Boolean Dim previousCharIsDigit As Boolean Dim lastParsedCharIsUnderscore As Boolean Dim firstCapitalizedLetterIsAdded As Boolean For i As Integer = 0 To name.Length - 1 Dim c As Char = name(i) If i = 0 Then If c.Equals("_"c) Then sb.Append(Convert.ToChar(Convert.ToChar(&H205F))) lastParsedCharIsUnderscore = True Else sb.Append(Char.ToUpper(c)) firstCapitalizedLetterIsAdded = True End If Continue For End If previousChar = sb.Chars(sb.Length - 1) previousCharIsWhiteSpace = previousChar.Equals(" "c) OrElse previousChar.Equals(Convert.ToChar(&H205F)) previousCharIsUpperLetter = Char.IsUpper(previousChar) previousCharIsDigit = Char.IsDigit(previousChar) If Char.IsLetter(c) Then If previousCharIsDigit AndAlso Not previousCharIsWhiteSpace Then sb.Append(" "c) End If If Char.IsUpper(c) Then If previousCharIsUpperLetter Then sb.Append(c) ElseIf Not previousCharIsWhiteSpace Then sb.Append(" "c) sb.Append(c) Else sb.Append(c) End If firstCapitalizedLetterIsAdded = True Else If Not firstCapitalizedLetterIsAdded Then sb.Append(Char.ToUpper(c)) firstCapitalizedLetterIsAdded = True Else sb.Append(c) End If End If ElseIf Char.IsDigit(c) Then If Not previousCharIsDigit AndAlso Not previousCharIsWhiteSpace Then sb.Append(" "c) End If sb.Append(c) ElseIf c.Equals("_"c) Then If lastParsedCharIsUnderscore OrElse Not previousCharIsWhiteSpace Then sb.Append(Convert.ToChar(&H205F)) ' Unicode white-space: " " lastParsedCharIsUnderscore = True End If Else sb.Append(c) lastParsedCharIsUnderscore = False End If Next i Return sb.ToString() End Function End Class
|
|
|
4
|
Programación / .NET (C#, VB.NET, ASP) / Re: Librería de Snippets para VB.NET !! (Compartan aquí sus snippets)
|
en: 26 Abril 2024, 18:38 pm
|
Comparto una forma que he ideado para automatizar la traducción, al idioma actual de la aplicación, los valores booleanos en un propertygrid (por ejemplo), mediante el uso clases de atributos.
El modo de empleo es muy sencillo: public class TestClass <LocalizableBoolean> <TypeConverter(GetType(LocalizableBooleanConverter))> Public Property FeatureEnabled As Boolean = True end class
Me.PropertyGrid1.SelectedObject = new TestClass()
También se puede utilizar de esta forma alternativa para una representación arbitraria en los idiomas que se especifiquen mediante un string separado por comas (en este ejemplo, el español y el francés): <LocalizableBoolean("es, fr", "ssssí!!, Oui!", "nope!, Non!")> <TypeConverter(GetType(LocalizableBooleanConverter))> Public Property FeatureEnabled As Boolean = True
El código:LocalizedBoolean.vb ''' <summary> ''' Represents localized strings for <see langword="True"/> and <see langword="False"/> <see cref="Boolean"/> values. ''' </summary> <DebuggerStepThrough> Public NotInheritable Class LocalizedBoolean ''' <summary> ''' The <see cref="CultureInfo"/> that represents the region for ''' the localized strings in <see cref="LocalizedBoolean.True"/> ''' and <see cref="LocalizedBoolean.False"/> properties. ''' </summary> Public ReadOnly Property Culture As CultureInfo ''' <summary> ''' The localized string representation for <see langword="True"/> <see cref="Boolean"/> value. ''' </summary> Public ReadOnly Property [True] As String ''' <summary> ''' The localized string representation for <see langword="False"/> <see cref="Boolean"/> value. ''' </summary> Public ReadOnly Property [False] As String ''' <summary> ''' Initializes a new instance of the <see cref="LocalizedBoolean"/> class. ''' </summary> ''' ''' <param name="culture"> ''' The <see cref="CultureInfo"/> that represents the region for the localized strings. ''' </param> ''' ''' <param name="trueString"> ''' The localized string representation for <see langword="True"/> <see cref="Boolean"/> value. ''' </param> ''' ''' <param name="falseString"> ''' The localized string representation for <see langword="False"/> <see cref="Boolean"/> value. ''' </param> Public Sub New(culture As CultureInfo, trueString As String, falseString As String) If culture Is Nothing Then Throw New ArgumentNullException(paramName:=NameOf(culture)) End If If String.IsNullOrWhiteSpace(trueString) Then Throw New ArgumentNullException(paramName:=NameOf(trueString)) End If If String.IsNullOrWhiteSpace(falseString) Then Throw New ArgumentNullException(paramName:=NameOf(falseString)) End If Me.Culture = culture Me.True = trueString Me.False = falseString End Sub ''' <summary> ''' Prevents a default instance of the <see cref="LocalizedBoolean"/> class from being created. ''' </summary> Private Sub New() End Sub End Class
LocalizableBooleanAttribute.vb ''' <summary> ''' Specifies that a <see cref="Boolean"/> property can display localized string representations ''' for <see langword="True"/> and <see langword="False"/> values. ''' </summary> <AttributeUsage(AttributeTargets.Property, AllowMultiple:=False, Inherited:=True)> <DebuggerStepThrough> Public NotInheritable Class LocalizableBooleanAttribute : Inherits Attribute
''' <summary> ''' Gets the localized boolean representations. ''' <para></para> ''' The dictionary Key is the ISO 639-1 two-letter code for the language. ''' </summary> Public ReadOnly Property Localizations As Dictionary(Of String, LocalizedBoolean)
''' <summary> ''' Initializes a new instance of the <see cref="LocalizedBoolean"/> class. ''' </summary> Public Sub New() Me.Localizations = New Dictionary(Of String, LocalizedBoolean)(StringComparison.OrdinalIgnoreCase) From { {"af", New LocalizedBoolean(CultureInfo.GetCultureInfo("af"), "Ja", "Nee")}, ' Afrikaans {"am", New LocalizedBoolean(CultureInfo.GetCultureInfo("am"), "እወዳለሁ", "አይደለሁ")}, ' Amharic {"ar", New LocalizedBoolean(CultureInfo.GetCultureInfo("ar"), "نعم", "لا")}, ' Arabic {"az", New LocalizedBoolean(CultureInfo.GetCultureInfo("az"), "Bəli", "Xeyr")}, ' Azerbaijani {"be", New LocalizedBoolean(CultureInfo.GetCultureInfo("be"), "Так", "Не")}, ' Belarusian {"bg", New LocalizedBoolean(CultureInfo.GetCultureInfo("bg"), "Да", "Не")}, ' Bulgarian {"bn", New LocalizedBoolean(CultureInfo.GetCultureInfo("bn"), "হ্যাঁ", "না")}, ' Bengali {"ca", New LocalizedBoolean(CultureInfo.GetCultureInfo("ca"), "Sí", "No")}, ' Catalan {"cs", New LocalizedBoolean(CultureInfo.GetCultureInfo("cs"), "Ano", "Ne")}, ' Czech {"cy", New LocalizedBoolean(CultureInfo.GetCultureInfo("cy"), "Ie", "Na")}, ' Welsh {"da", New LocalizedBoolean(CultureInfo.GetCultureInfo("da"), "Ja", "Nej")}, ' Danish {"de", New LocalizedBoolean(CultureInfo.GetCultureInfo("de"), "Ja", "Nein")}, ' German {"el", New LocalizedBoolean(CultureInfo.GetCultureInfo("el"), "Ναι", "Όχι")}, ' Greek {"en", New LocalizedBoolean(CultureInfo.GetCultureInfo("en"), "Yes", "No")}, ' English {"es", New LocalizedBoolean(CultureInfo.GetCultureInfo("es"), "Sí", "No")}, ' Spanish {"et", New LocalizedBoolean(CultureInfo.GetCultureInfo("et"), "Jah", "Ei")}, ' Estonian {"eu", New LocalizedBoolean(CultureInfo.GetCultureInfo("eu"), "Bai", "Ez")}, ' Basque {"fa", New LocalizedBoolean(CultureInfo.GetCultureInfo("fa"), "بله", "خیر")}, ' Persian {"fi", New LocalizedBoolean(CultureInfo.GetCultureInfo("fi"), "Kyllä", "Ei")}, ' Finnish {"fr", New LocalizedBoolean(CultureInfo.GetCultureInfo("fr"), "Oui", "Non")}, ' French {"ga", New LocalizedBoolean(CultureInfo.GetCultureInfo("ga"), "Tá", "Níl")}, ' Irish {"gd", New LocalizedBoolean(CultureInfo.GetCultureInfo("gd"), "Tha", "Chan eil")}, ' Scottish Gaelic {"gl", New LocalizedBoolean(CultureInfo.GetCultureInfo("gl"), "Si", "Non")}, ' Galician {"gu", New LocalizedBoolean(CultureInfo.GetCultureInfo("gu"), "હા", "ના")}, ' Gujarati {"hi", New LocalizedBoolean(CultureInfo.GetCultureInfo("hi"), "हाँ", "नहीं")}, ' Hindi {"hr", New LocalizedBoolean(CultureInfo.GetCultureInfo("hr"), "Da", "Ne")}, ' Croatian {"ht", New LocalizedBoolean(CultureInfo.GetCultureInfo("ht"), "Wi", "Pa")}, ' Haitian Creole {"hu", New LocalizedBoolean(CultureInfo.GetCultureInfo("hu"), "Igen", "Nem")}, ' Hungarian {"id", New LocalizedBoolean(CultureInfo.GetCultureInfo("id"), "Ya", "Tidak")}, ' Indonesian {"ig", New LocalizedBoolean(CultureInfo.GetCultureInfo("ig"), "Ee", "Mba")}, ' Igbo {"is", New LocalizedBoolean(CultureInfo.GetCultureInfo("is"), "Já", "Nei")}, ' Icelandic {"it", New LocalizedBoolean(CultureInfo.GetCultureInfo("it"), "Sì", "No")}, ' Italian {"ja", New LocalizedBoolean(CultureInfo.GetCultureInfo("ja"), "はい", "いいえ")}, ' Japanese {"jv", New LocalizedBoolean(CultureInfo.GetCultureInfo("jv"), "Iya", "Ora")}, ' Javanese {"kk", New LocalizedBoolean(CultureInfo.GetCultureInfo("kk"), "Иә", "Жоқ")}, ' Kazakh {"km", New LocalizedBoolean(CultureInfo.GetCultureInfo("km"), "បាទ/ចាស", "ទេ")}, ' Khmer {"kn", New LocalizedBoolean(CultureInfo.GetCultureInfo("kn"), "ಹೌದು", "ಇಲ್ಲ")}, ' Kannada {"ko", New LocalizedBoolean(CultureInfo.GetCultureInfo("ko"), "예", "아니오")}, ' Korean {"ku", New LocalizedBoolean(CultureInfo.GetCultureInfo("ku"), "Belê", "Na")}, ' Kurdish (Kurmanji) {"ky", New LocalizedBoolean(CultureInfo.GetCultureInfo("ky"), "Ооба", "Жок")}, ' Kyrgyz {"la", New LocalizedBoolean(CultureInfo.GetCultureInfo("la"), "Ita", "Non")}, ' Latin {"lg", New LocalizedBoolean(CultureInfo.GetCultureInfo("lg"), "Yee", "Nedda")}, ' Luganda {"lt", New LocalizedBoolean(CultureInfo.GetCultureInfo("lt"), "Taip", "Ne")}, ' Lithuanian {"lv", New LocalizedBoolean(CultureInfo.GetCultureInfo("lv"), "Jā", "Nē")}, ' Latvian {"mg", New LocalizedBoolean(CultureInfo.GetCultureInfo("mg"), "Eny", "Tsia")}, ' Malagasy {"mi", New LocalizedBoolean(CultureInfo.GetCultureInfo("mi"), "Āe", "Kāo")}, ' Maori {"mk", New LocalizedBoolean(CultureInfo.GetCultureInfo("mk"), "Да", "Не")}, ' Macedonian {"ml", New LocalizedBoolean(CultureInfo.GetCultureInfo("ml"), "അതെ", "ഇല്ല")}, ' Malayalam {"mn", New LocalizedBoolean(CultureInfo.GetCultureInfo("mn"), "Тийм", "Үгүй")}, ' Mongolian {"mr", New LocalizedBoolean(CultureInfo.GetCultureInfo("mr"), "होय", "नाही")}, ' Marathi {"ms", New LocalizedBoolean(CultureInfo.GetCultureInfo("ms"), "Ya", "Tidak")}, ' Malay {"mt", New LocalizedBoolean(CultureInfo.GetCultureInfo("mt"), "Iva", "Le")}, ' Maltese {"my", New LocalizedBoolean(CultureInfo.GetCultureInfo("my"), "ဟုတ်ကဲ့", "မဟုတ်ဘူး")}, ' Burmese {"ne", New LocalizedBoolean(CultureInfo.GetCultureInfo("ne"), "हो", "होइन")}, ' Nepali {"nl", New LocalizedBoolean(CultureInfo.GetCultureInfo("nl"), "Ja", "Nee")}, ' Dutch {"no", New LocalizedBoolean(CultureInfo.GetCultureInfo("no"), "Ja", "Nei")}, ' Norwegian {"ny", New LocalizedBoolean(CultureInfo.GetCultureInfo("ny"), "Yewo", "Ayawo")}, ' Chichewa {"pa", New LocalizedBoolean(CultureInfo.GetCultureInfo("pa"), "ਹਾਂ", "ਨਹੀਂ")}, ' Punjabi {"pl", New LocalizedBoolean(CultureInfo.GetCultureInfo("pl"), "Tak", "Nie")}, ' Polish {"ps", New LocalizedBoolean(CultureInfo.GetCultureInfo("ps"), "هو", "نه")}, ' Pashto {"pt", New LocalizedBoolean(CultureInfo.GetCultureInfo("pt"), "Sim", "Não")}, ' Portuguese {"rm", New LocalizedBoolean(CultureInfo.GetCultureInfo("rm"), "Gia", "Betg")}, ' Romansh {"ro", New LocalizedBoolean(CultureInfo.GetCultureInfo("ro"), "Da", "Nu")}, ' Romanian {"ru", New LocalizedBoolean(CultureInfo.GetCultureInfo("ru"), "Да", "Нет")}, ' Russian {"sd", New LocalizedBoolean(CultureInfo.GetCultureInfo("sd"), "هاڻي", "نه")}, ' Sindhi {"si", New LocalizedBoolean(CultureInfo.GetCultureInfo("si"), "ඔව්", "නැත")}, ' Sinhala {"sk", New LocalizedBoolean(CultureInfo.GetCultureInfo("sk"), "Áno", "Nie")}, ' Slovak {"sl", New LocalizedBoolean(CultureInfo.GetCultureInfo("sl"), "Da", "Ne")}, ' Slovenian {"sm", New LocalizedBoolean(CultureInfo.GetCultureInfo("sm"), "Ioe", "Leai")}, ' Samoan {"sn", New LocalizedBoolean(CultureInfo.GetCultureInfo("sn"), "Yebo", "Cha")}, ' Shona {"so", New LocalizedBoolean(CultureInfo.GetCultureInfo("so"), "Haa", "Maya")}, ' Somali {"sq", New LocalizedBoolean(CultureInfo.GetCultureInfo("sq"), "Po", "Jo")}, ' Albanian {"sr", New LocalizedBoolean(CultureInfo.GetCultureInfo("sr"), "Да", "Не")}, ' Serbian (Cyrillic) {"su", New LocalizedBoolean(CultureInfo.GetCultureInfo("su"), "Iya", "Teu")}, ' Sundanese {"sv", New LocalizedBoolean(CultureInfo.GetCultureInfo("sv"), "Ja", "Nej")}, ' Swedish {"sw", New LocalizedBoolean(CultureInfo.GetCultureInfo("sw"), "Ndiyo", "Hapana")}, ' Swahili {"ta", New LocalizedBoolean(CultureInfo.GetCultureInfo("ta"), "ஆம்", "இல்லை")}, ' Tamil {"te", New LocalizedBoolean(CultureInfo.GetCultureInfo("te"), "అవును", "కాదు")}, ' Telugu {"tg", New LocalizedBoolean(CultureInfo.GetCultureInfo("tg"), "Ҳа", "Не")}, ' Tajik {"th", New LocalizedBoolean(CultureInfo.GetCultureInfo("th"), "ใช่", "ไม่")}, ' Thai {"ti", New LocalizedBoolean(CultureInfo.GetCultureInfo("ti"), "እወ", "አይወ")}, ' Tigrinya {"tk", New LocalizedBoolean(CultureInfo.GetCultureInfo("tk"), "Hawa", "Ýok")}, ' Turkmen {"to", New LocalizedBoolean(CultureInfo.GetCultureInfo("to"), "ʻIo", "ʻEa")}, ' Tongan {"tr", New LocalizedBoolean(CultureInfo.GetCultureInfo("tr"), "Evet", "Hayır")}, ' Turkish {"tt", New LocalizedBoolean(CultureInfo.GetCultureInfo("tt"), "Әйе", "Юк")}, ' Tatar {"ug", New LocalizedBoolean(CultureInfo.GetCultureInfo("ug"), "ھەئە", "ياق")}, ' Uighur {"uk", New LocalizedBoolean(CultureInfo.GetCultureInfo("uk"), "Так", "Ні")}, ' Ukrainian {"ur", New LocalizedBoolean(CultureInfo.GetCultureInfo("ur"), "جی ہاں", "نہیں")}, ' Urdu {"uz", New LocalizedBoolean(CultureInfo.GetCultureInfo("uz"), "Ha", "Yo'q")}, ' Uzbek {"vi", New LocalizedBoolean(CultureInfo.GetCultureInfo("vi"), "Có", "Không")}, ' Vietnamese {"xh", New LocalizedBoolean(CultureInfo.GetCultureInfo("xh"), "Ewe", "Hayi")}, ' Xhosa {"yi", New LocalizedBoolean(CultureInfo.GetCultureInfo("yi"), "יאָ", "ניי")}, ' Yiddish {"yo", New LocalizedBoolean(CultureInfo.GetCultureInfo("yo"), "Bẹẹni", "Bẹẹkoo")}, ' Yoruba {"zh", New LocalizedBoolean(CultureInfo.GetCultureInfo("zh"), "是", "不")}, ' Chinese (Simplified) {"zu", New LocalizedBoolean(CultureInfo.GetCultureInfo("zu"), "Yebo", "Cha")} ' Zulu } End Sub
''' <summary> ''' Initializes a new instance of the <see cref="LocalizedBoolean"/> class. ''' </summary> ''' ''' <param name="cultureNames"> ''' A comma-separated value of the ISO 639-1 two-letter code languages (e.g.: "en,es,fr"). ''' </param> ''' ''' <param name="trueStrings"> ''' A comma-separated value of the localized string representation for "True" boolean value (e.g.: "Yes,Sí,Oui"). ''' </param> ''' ''' <param name="falseStrings"> ''' A comma-separated value of the localized string representation for "False" boolean value (e.g.: "No,No,Non"). ''' </param> Public Sub New(cultureNames As String, trueStrings As String, falseStrings As String) Me.New()
If String.IsNullOrWhiteSpace(cultureNames) Then Throw New ArgumentNullException(paramName:=NameOf(cultureNames)) End If If String.IsNullOrWhiteSpace(trueStrings) Then Throw New ArgumentNullException(paramName:=NameOf(trueStrings)) End If If String.IsNullOrWhiteSpace(falseStrings) Then Throw New ArgumentNullException(paramName:=NameOf(falseStrings)) End If
Dim cultureNamesArray As String() = cultureNames.Split({","c}, StringSplitOptions.RemoveEmptyEntries) Dim trueStringsArray As String() = trueStrings.Split({","c}, StringSplitOptions.RemoveEmptyEntries) Dim falseStringsArray As String() = falseStrings.Split({","c}, StringSplitOptions.RemoveEmptyEntries)
If cultureNamesArray.Length <> trueStringsArray.Length OrElse cultureNamesArray.Length <> falseStringsArray.Length Then Throw New InvalidOperationException("The comma-separated values must have the same amount of tokens.") End If
For i As Integer = 0 To cultureNamesArray.Length - 1 Dim cultureName As String = cultureNamesArray(i).Trim() Dim trueString As String = trueStringsArray(i).Trim() Dim falseString As String = falseStringsArray(i).Trim()
If cultureName.Length <> 2 Then Throw New InvalidOperationException("The culture name must be a ISO 639-1 two-letter code.") End If
Dim localizedBoolean As New LocalizedBoolean(CultureInfo.GetCultureInfo(cultureName), trueString, falseString) If Me.Localizations.ContainsKey(cultureName) Then Me.Localizations(cultureName) = localizedBoolean Else Me.Localizations.Add(cultureName, localizedBoolean) End If Next End Sub
End Class LocalizableBooleanConverter.vb ''' <summary> ''' Provides conversion functionality between Boolean values and localized strings representing "True" and "False" boolean values. ''' </summary> Public Class LocalizableBooleanConverter : Inherits TypeConverter ''' <summary> ''' The localized string representation for "True" boolean value. ''' </summary> Private trueString As String = "Yes" ''' <summary> ''' The localized string representation for "False" boolean value. ''' </summary> Private falseString As String = "No" ''' <summary> ''' Returns whether this converter can convert an object of the given type to the type of this converter, ''' using the specified context. ''' </summary> ''' ''' <param name="context"> ''' An <see cref="ITypeDescriptorContext"/> that provides a format context. ''' </param> ''' ''' <param name="sourceType"> ''' A <see cref="Type" /> that represents the type you want to convert from. ''' </param> ''' ''' <returns> ''' <see langword="True"/> if this converter can perform the conversion; otherwise, <see langword="False"/>. ''' </returns> Public Overrides Function CanConvertFrom(context As ITypeDescriptorContext, sourceType As Type) As Boolean Return sourceType = GetType(String) OrElse MyBase.CanConvertFrom(context, sourceType) End Function ''' <summary> ''' Returns whether this converter can convert the object to the specified type, using the specified context. ''' </summary> ''' ''' <param name="context"> ''' An <see cref="ITypeDescriptorContext"/> that provides a format context. ''' </param> ''' ''' <param name="destinationType"> ''' A <see cref="Type"/> that represents the type you want to convert to. ''' </param> ''' ''' <returns> ''' <see langword="True"/> if this converter can perform the conversion; otherwise, <see langword="False"/>. ''' </returns> Public Overrides Function CanConvertTo(context As ITypeDescriptorContext, destinationType As Type) As Boolean Return destinationType = GetType(String) OrElse MyBase.CanConvertTo(context, destinationType) End Function ''' <summary> ''' Converts the given object to the type of this converter, using the specified context and culture information. ''' </summary> ''' ''' <param name="context"> ''' An <see cref="ITypeDescriptorContext"/> that provides a format context. ''' </param> ''' ''' <param name="culture"> ''' The <see cref="CultureInfo"/> to use as the current culture. ''' </param> ''' ''' <param name="value"> ''' The <see cref="Object"/> to convert. ''' </param> ''' ''' <returns> ''' An <see cref="Object"/> that represents the converted value. ''' </returns> <DebuggerStepperBoundary> Public Overrides Function ConvertFrom(context As ITypeDescriptorContext, culture As Globalization.CultureInfo, value As Object) As Object If TypeOf value Is String Then Dim stringValue As String = DirectCast(value, String) If String.Equals(stringValue, Me.trueString, StringComparison.OrdinalIgnoreCase) Then Return True ElseIf String.Equals(stringValue, Me.FalseString, StringComparison.OrdinalIgnoreCase) Then Return False End If End If Return MyBase.ConvertFrom(context, culture, value) End Function ''' <summary> ''' Converts the given value object to the specified type, using the specified context and culture information. ''' </summary> ''' ''' <param name="context"> ''' An <see cref="ITypeDescriptorContext"/> that provides a format context. ''' </param> ''' ''' <param name="culture"> ''' A <see cref="CultureInfo"/>. If null is passed, the current culture is assumed. ''' </param> ''' ''' <param name="value"> ''' The <see cref="Object"/> to convert. ''' </param> ''' ''' <param name="destinationType"> ''' The <see cref="Type"/> to convert the <paramref name="value"/> parameter to. ''' </param> ''' ''' <returns> ''' An <see cref="Object"/> that represents the converted value. ''' </returns> <DebuggerStepperBoundary> Public Overrides Function ConvertTo(context As ITypeDescriptorContext, culture As Globalization.CultureInfo, value As Object, destinationType As Type) As Object If context IsNot Nothing Then Dim attributes As IEnumerable(Of LocalizableBooleanAttribute) = context.PropertyDescriptor.Attributes.OfType(Of LocalizableBooleanAttribute) For Each attr As LocalizableBooleanAttribute In attributes Dim uiCulture As CultureInfo = My.Application.UICulture Dim localizedBoolean As LocalizedBoolean = Nothing If attr.Localizations.ContainsKey(uiCulture.TwoLetterISOLanguageName) Then localizedBoolean = attr.Localizations(uiCulture.TwoLetterISOLanguageName) End If If localizedBoolean IsNot Nothing Then Me.trueString = localizedBoolean.True Me.falseString = localizedBoolean.False End If Next End If If destinationType = GetType(String) Then If TypeOf value Is Boolean Then Dim boolValue As Boolean = value Return If(boolValue, Me.trueString, Me.falseString) End If End If Return MyBase.ConvertTo(context, culture, value, destinationType) End Function ''' <summary> ''' Returns a collection of standard values for the data type this type converter is designed for when provided with a format context. ''' </summary> ''' ''' <param name="context"> ''' An <see cref="ITypeDescriptorContext"/> that provides a format context that can be used to ''' extract additional information about the environment from which this converter is invoked. ''' <para></para> ''' This parameter or properties of this parameter can be null. ''' </param> ''' ''' <returns> ''' A <see cref="StandardValuesCollection"/> that holds a standard set of valid values, ''' or <see langword="null" /> if the data type does not support a standard set of values. ''' </returns> Public Overrides Function GetStandardValues(context As ITypeDescriptorContext) As StandardValuesCollection Return New StandardValuesCollection(New Boolean() {True, False}) End Function ''' <summary> ''' Returns whether this object supports a standard set of values that can be picked from a list, using the specified context. ''' </summary> ''' ''' <param name="context"> ''' An <see cref="ITypeDescriptorContext" /> that provides a format context. ''' </param> ''' ''' <returns> ''' <see langword="True"/> if <see cref="TypeConverter.GetStandardValues"/> should be called to ''' find a common set of values the object supports; otherwise, <see langword="False"/>. ''' </returns> Public Overrides Function GetStandardValuesSupported(context As ITypeDescriptorContext) As Boolean Return True End Function End Class
NOTA: El diccionario con los idiomas y sus equivalentes para "Sí" y "No", lo ha generado ChatGPT. Puede haber fallos en las traducciones, o en los códigos ISO 639-1 de dos letras. Además, faltaría añadir muchos más idiomas: https://en.wikipedia.org/wiki/List_of_ISO_639_language_codes
|
|
|
5
|
Media / Multimedia / Re: Busco: Programa para editar (cortar/pegar) un archivo de audio AC-3 sin volver a codificarlo
|
en: 25 Abril 2024, 01:52 am
|
No es lo que estoy buscando, Daniel, pero gracias una vez más por ayudar.
Elektro creo que tengo lo que buscas, osea un programa que trabaje con ac3 sin recodificar. Al menos cortar corta por que lo e probado yo mismo. Las demás funciones tendrás que comprobarlo tu. Se trata del Shutter Encoder, y puedes bajarlo de aquí: https://www.shutterencoder.com Suerte y saludos...
Songoku Pues.... ¡oye!, se hace algo tediosa de manejar, tan en pequeñito y escondido todo, pero lo cierto es que la función de cortar (que no es la que se llama "cortar", sino "eliminar") funciona perfectamente para cortar un segmento y preservar todo lo demás del lado izquierdo y derecho del segmento cortado, sin recodificar. Lo he probado con un audio AC-3 de 2, y 6 canales. Si el programa tuviese una función adicional para añadir un silencio en un punto específico, eso ya sería maravilloso, pero creo que esa funcionalidad no está implementada. Lo bueno es que es open-source y el proyecto parece bastante activo, así que... preguntaré a ver si el autor puede añadir esa función en el futuro. Yo soy muy exigente (intento buscar el perfeccionismo), pero también soy realista, y con lo difícil que es encontrar un programa que cumpla con una o varias de estas funcionalidades... creo que por ahora no se le puede pedir más. Cortar era lo principal. Al final lo lograste, Songoku, ¡MUCHAS GRACIAS!.
|
|
|
6
|
Media / Multimedia / Re: Busco: Programa para editar (cortar/pegar) un archivo de audio AC-3 sin volver a codificarlo
|
en: 22 Abril 2024, 17:43 pm
|
Hola, algo que se me ocurrió de probar es convertir el audio AC-3 a mp3, hacer la edición con mp3DirectCut y volver a convertirlo a AC-3. Como ya te han sugerido, Audacity es bastante bueno para eso. Tengo las herramientas para llevar a cabo ese procedimiento, pero quiero evitarlo. Cualquier procedimiento que implique convertir/recodificar el audio original AC-3 a otro formato compatible con el editor de audio en cuestión, no me sirve. Además, si el audio AC-3 es 5.1, los canales adicionales se pierden (se unen) en la conversión a MP3 estéreo (2 canales).
eso de poder cortar un trozo es posible hacerlo sin recodificar siempre que lo que cortes y pegues sea del mismo archivo, pero si pretendes como me a parecido entender En realidad yo lo que pretendo es hacer cortes y pegar segmentos del mismo audio que esté editando en ese momento; no tengo intención de hacer nada que no se haría con un MP3 en el programa "mp3DirectCut".
dependiendo de lo que quieras hacer no va a quedar mas remedio que recodificar, no es cuestión de un software u otro. La recodificación es obligatoria, siempre que cortes o añadas a la línea de tiempo. No quiero parecer cabezota, y os agradezco la ayuda a los cuatro, pero estoy convencido de que la recodificación no es obligatoria... Simplemente tenemos esa percepción de obligatoriedad, por que no hemos descubierto un software que nos permita, de forma tan versátil y guiada como "mp3DirectCut", trabajar directamente sobre archivos AC-3. Quizás simplemente es que todavía nadie ha desarrollado un software así, o quizás sí, pero sea muy poco conocido y por ende difícil de hallar. Pero en mi anterior comentario mencioné un programa por nombre "DelayCut" que se acerca algo... se acerca bastante, y cumple con el requisito de trabajar directamente (de forma lossless) sobre el archivo AC-3, aunque la forma en que se presenta la interfaz de usuario deja muchísimo que desear, sin un visualizador de ondas para reproducir el audio y permitir seleccionar un segmento que cortar (o insertar un silencio o pegar) no sirve de mucho para ciertas tareas de edición de audio, la verdad. Antes de darme por vencido necesito seguir buscando, manteniendo la esperanza en encontrar este tipo de programa. Gracias de nuevo.
|
|
|
7
|
Media / Multimedia / Re: Busco: Programa para editar (cortar/pegar) un archivo de audio AC-3 sin volver a codificarlo
|
en: 22 Abril 2024, 00:32 am
|
da igual si sea en ac3 o en el formato que sea, osea algunas actuaciones requieren recodificación, y eso vale para CUALQUIER programa.
En realidad, Songoku, hay editores de audio, como por ejemplo mp3DirectCut, que sirve para realizar cortes, pegar, añadir silencios, hacer fade-in/fade-out entre otras cosas, y con soporte directo para los formatos MP3, MP2 y AAC, pues este programa, entre otros, es capaz de realizar todas estas ediciones directamente sobre el archivo, o también se puede guardar a un nuevo archivo, creando el archivo sin recodificación de la pista de audio editada. Pero vamos tampoco le veo el problema. Con Audacity (por mencionar uno de tantos editores de audio), al requerir recodificar, se pierde calidad. La pérdida en la calidad de audio puede ser mínima / ínfima / imperceptible si se codifica usando el mismo codec, mismo bitrate y los parámetros de calidad adecuados, pero siempre se va a perder una cantidad mínima, que aunque sea imperceptible, pues se pierde, y yo quiero intentar evitarlo. En cambio, con un editor de audio que no necesitase recodificar (como mp3DirectCut), se garantiza que la calidad de audio se mantenga intacta, sin perder ni una "milésima" de calidad por imperceptible que fuese. Esto es lo que se denomina "LOSSLESS" (edición sin pérdidas) y es el tipo de edición que busco, pero para formato AC-3. Otra opción pero de pago sería el MAGIX Sound Forge Audio Studio. Se supone que lo que no haga ese programa no lo podrá hacer nadie. Pero vamos como ya digo los milagros no existen y ciertas cosas son imposibles para cualquier programa. Saludos... Ni el Sound Forge ni el Vegas permiten editar de forma lossless. Lo que busco es complicado, pero no imposible. Mira, un programa que se acerca a lo que busco es DelayCut ( https://www.videohelp.com/software/delaycut) capaz de añadir silencios a pistas AC-3 de forma lossless. El programa tiene una función para hacer cortes, pero... esa función de cortar no sirve para realizar cortes de un segmento específico en el audio (digamos, por ejemplo, que no sirve para hacer un corte desde el segundo 10, hasta el segundo 11, dejando intacto el audio anterior al segundo 10 y el audio posterior al segundo 11), o al menos yo no lo he sabido utilizar de esa forma, y además es que la interfaz gráfica... no hay visualizador de ondas, por lo que se ha de introducir manualmente los códigos de tiempo... ni siquiera eso, no se pueden introducir códigos de tiempo para hacerlo algo más fácil, sino que hay que introducir valores en milisegundos (o en otros formatos, pero valores en general que no son códigos de tiempo). Esto son cosas que puedo hacer perfectamente con otros programas command-line (ej. FFMPEG) y de forma mucho menos tediosa. No es lo que busco. Gracias igualmente, seguiré buscando!
|
|
|
9
|
Media / Multimedia / Busco: Programa para editar (cortar/pegar) un archivo de audio AC-3 sin volver a codificarlo
|
en: 21 Abril 2024, 18:11 pm
|
Me gustaría descubrir un programa para Windows, con una interfaz gráfica de usuario, que sea capaz de cargar un archivo de audio AC-3 para cortar (y pegar) en algunos puntos del stream de audio, sin volver a codificar el audio. Cuando pienso en este tipo de aplicación, lo ideal sería que tuviera similitud con la interfaz de usuario de mp3DirectCut ( https://mpesch3.de/): Requisitos: ----------- - Freeware (de código abierto o no, no importa) o Freemium (parcialmente gratuito con funciones premium deshabilitadas). - Funciona en Windows 10 (x64). - Con interfaz gráfica de usuario (GUI) donde puedes seleccionar un rango, por lo que no necesitas ingresar manualmente los códigos de tiempo para cortar. - Tiene un visualizador de flujo de audio (o "visualizador de ondas"), como en la captura de pantalla anterior. - Puede reproducir el audio, cortarlo en cualquier punto y pegar un silencio en cualquier punto. - Edición sin pérdidas, "lossless" (es decir, no requiere volver a codificar el archivo de audio). - Soporta estéreo o canales 5.1. Nota: las sugerencias de software pago también son bienvenidas, si son económicas para uso privado (no soluciones corporativas que cuestan cientos o miles de euros). Muchas gracias por su atención.
|
|
|
10
|
Programación / .NET (C#, VB.NET, ASP) / Re: Librería de Snippets para VB.NET !! (Compartan aquí sus snippets)
|
en: 19 Abril 2024, 18:48 pm
|
El siguiente código es un módulo por nombre ' Wildcard' que representa un algoritmo de coincidencia de cadenas con uso de comodines * ( wildcards). Sirve como alternativa al operador Like de VB.NET. Ejemplo de uso: Dim input As String = "Hello World!" Dim pattern As String = "*e*l*o *!" Console.WriteLine($"{NameOf(Wildcard.IsMatch)} {Wildcard.IsMatch(input, pattern)}")
El código lo he extraído del código fuente de la aplicación "RomyView" escrita en C#: Lo he convertido a VB.NET de forma automática, y lo comparto tal cual, sin modificaciones ni adiciones. Lo he probado con varias cadenas y combinaciones de patrones de comodines, y parece funcionar a la perfección. Wildcard.vb''' <summary>The IsMatch function below was downloaded from: ''' <a href="https://www.c-sharpcorner.com/uploadfile/b81385/efficient-string-matching-algorithm-with-use-of-wildcard-characters/"> ''' Efficient String Matching Algorithm with Use of Wildcard Characters</a></summary> Public Module Wildcard ''' <summary>Tests whether specified string can be matched against provided pattern string, where ''' the pattern string may contain wildcards as follows: ? to replace any single character, and * ''' to replace any string.</summary> ''' <param name="input">String which is matched against the pattern.</param> ''' <param name="pattern">Pattern against which string is matched.</param> ''' <returns>true if <paramref name="pattern"/> matches the string <paramref name="input"/>; otherwise false.</returns> Public Function IsMatch(input As String, pattern As String) As Boolean Return IsMatch(input, pattern, "?"c, "*"c) End Function ''' <summary>Tests whether specified string can be matched against provided pattern string. ''' Pattern may contain single- and multiple-replacing wildcard characters.</summary> ''' <param name="input">String which is matched against the pattern.</param> ''' <param name="pattern">Pattern against which string is matched.</param> ''' <param name="singleWildcard">Character which can be used to replace any single character in input string.</param> ''' <param name="multipleWildcard">Character which can be used to replace zero or more characters in input string.</param> ''' <returns>true if <paramref name="pattern"/> matches the string <paramref name="input"/>; otherwise false.</returns> Public Function IsMatch(input As String, pattern As String, singleWildcard As Char, multipleWildcard As Char) As Boolean Dim inputPosStack(((input.Length + 1) * (pattern.Length + 1)) - 1) As Integer ' Stack containing input positions that should be tested for further matching Dim patternPosStack(inputPosStack.Length - 1) As Integer ' Stack containing pattern positions that should be tested for further matching Dim stackPos As Integer = -1 ' Points to last occupied entry in stack; -1 indicates that stack is empty Dim pointTested()() As Boolean = { New Boolean(input.Length) {}, New Boolean(pattern.Length) {} } Dim inputPos As Integer = 0 ' Position in input matched up to the first multiple wildcard in pattern Dim patternPos As Integer = 0 ' Position in pattern matched up to the first multiple wildcard in pattern ' Match beginning of the string until first multiple wildcard in pattern Do While inputPos < input.Length AndAlso patternPos < pattern.Length AndAlso pattern.Chars(patternPos) <> multipleWildcard AndAlso (input.Chars(inputPos) = pattern.Chars(patternPos) OrElse pattern.Chars(patternPos) = singleWildcard) inputPos += 1 patternPos += 1 Loop ' Push this position to stack if it points to end of pattern or to a general wildcard If patternPos = pattern.Length OrElse pattern.Chars(patternPos) = multipleWildcard Then pointTested(0)(inputPos) = True pointTested(1)(patternPos) = True stackPos += 1 inputPosStack(stackPos) = inputPos patternPosStack(stackPos) = patternPos End If Dim matched As Boolean = False ' Repeat matching until either string is matched against the pattern or no more parts remain on stack to test Do While stackPos >= 0 AndAlso Not matched inputPos = inputPosStack(stackPos) ' Pop input and pattern positions from stack patternPos = patternPosStack(stackPos) ' Matching will succeed if rest of the input string matches rest of the pattern stackPos -= 1 If inputPos = input.Length AndAlso patternPos = pattern.Length Then matched = True ' Reached end of both pattern and input string, hence matching is successful Else ' First character in next pattern block is guaranteed to be multiple wildcard ' So skip it and search for all matches in value string until next multiple wildcard character is reached in pattern For curInputStart As Integer = inputPos To input.Length - 1 Dim curInputPos As Integer = curInputStart Dim curPatternPos As Integer = patternPos + 1 If curPatternPos = pattern.Length Then ' Pattern ends with multiple wildcard, hence rest of the input string is matched with that character curInputPos = input.Length Else Do While curInputPos < input.Length AndAlso curPatternPos < pattern.Length AndAlso pattern.Chars(curPatternPos) <> multipleWildcard AndAlso (input.Chars(curInputPos) = pattern.Chars(curPatternPos) OrElse pattern.Chars(curPatternPos) = singleWildcard) curInputPos += 1 curPatternPos += 1 Loop End If ' If we have reached next multiple wildcard character in pattern without breaking the matching sequence, then we have another candidate for full match ' This candidate should be pushed to stack for further processing ' At the same time, pair (input position, pattern position) will be marked as tested, so that it will not be pushed to stack later again If ((curPatternPos = pattern.Length AndAlso curInputPos = input.Length) OrElse (curPatternPos < pattern.Length AndAlso pattern.Chars(curPatternPos) = multipleWildcard)) AndAlso Not pointTested(0)(curInputPos) AndAlso Not pointTested(1)(curPatternPos) Then pointTested(0)(curInputPos) = True pointTested(1)(curPatternPos) = True stackPos += 1 inputPosStack(stackPos) = curInputPos patternPosStack(stackPos) = curPatternPos End If Next curInputStart End If Loop Return matched End Function End Module
|
|
|
|
|
|
|