ffmpeg -i out.wav -f s16le -ar 8000 -ac 1 -acodec pcm_s16le out.pcm
ffmpeg -i a.mp3 -f s16le -ar 8000 -ac 1 -acodec pcm_s16le a.pcm
参数说明
-ia.mp3源文件
-fs16le强制文件格式
-ar8000采样率
-ac1单声道
-acodecpcm_s16le编码器

在使用海康摄像头输出音频,选择pcm文件进行播放,如果摄像头解码器是G711 对应的pcm文件是采样率是8000,编码器 pcm_s16le

  public static object GetPropertyValue<TObject>(this PropertyInfo propertyInfo, TObject obj) where TObject : class
    {
        if (propertyInfo == null)
        {
            LoggerHandler.OnLogError("GetPropertyValue", new ArgumentNullException("propertyInfo null"));
            throw new ArgumentNullException("propertyInfo");
        }

        ParameterExpression parameterExpression = Expression.Parameter(typeof(TObject));
        return Expression.Lambda<Func<TObject, object>>(Expression.Convert(Expression.Property(Expression.Convert(parameterExpression, obj.GetType()), propertyInfo), typeof(object)), new ParameterExpression[1] { parameterExpression }).Compile()(obj);
    }
 public static void SetPropertyValue<TObject, TValue>(this PropertyInfo propertyInfo, TObject obj, TValue value)
    {
        if (propertyInfo == null)
        {
            LoggerHandler.OnLogError("SetPropertyValue", new ArgumentNullException("Property null"));
            throw new ArgumentNullException("propertyInfo");
        }

        if (propertyInfo.GetSetMethod() == null)
        {
            LoggerHandler.OnLogError("SetPropertyValue", new InvalidOperationException("Property does not have a setter"));
            throw new InvalidOperationException("Property does not have a setter");
        }

        ParameterExpression parameterExpression = Expression.Parameter(typeof(TObject));
        MemberExpression left = Expression.Property(Expression.Convert(parameterExpression, obj.GetType()), propertyInfo);
        ParameterExpression parameterExpression2 = Expression.Parameter(typeof(TValue));
        UnaryExpression right = Expression.Convert(parameterExpression2, propertyInfo.PropertyType);
        Expression.Lambda<Action<TObject, TValue>>(Expression.Assign(left, right), new ParameterExpression[2] { parameterExpression, parameterExpression2 }).Compile()(obj, value);
    }

线程(Threads)和协程(Coroutines)都是用于处理并发任务的编程概念,但它们有一些重要的区别。

线程:

  1. 线程是操作系统调度的最小执行单元。多个线程可以在同一进程内并发执行,共享进程的资源,如内存空间、文件描述符等。
  2. 线程之间的切换由操作系统负责,这个切换过程需要保存和恢复线程的上下文,因此线程切换的开销较大。
  3. 线程是抢占式的,意味着一个线程可以强制剥夺其他线程的执行权。
  4. 多线程编程需要考虑同步和资源竞争问题,比较容易出现并发错误,如死锁、竞态条件等。

协程:

  1. 协程是一种用户态的轻量级线程,也称为“微线程”或“纤程”。
  2. 协程由程序员显式地控制调度,可以通过主动让出执行权或者被其他协程显式调度来切换。
  3. 协程的切换开销相对较小,因为切换是在用户态进行,不需要操作系统的介入。
  4. 协程通常是合作式的,一个协程执行时需要主动让出执行权才能切换到其他协程。

主要区别:

  1. 调度方式:线程由操作系统内核调度,协程由用户程序自行调度。
  2. 切换开销:线程切换的开销较大,协程切换的开销相对较小。
  3. 合作与抢占:线程是抢占式的,而协程是合作式的。
  4. 编程模型:多线程编程需要考虑同步和竞争问题,而协程更加轻量,不需要显式的同步操作,更容易编写和维护。

协程在某些场景下能够提供更高的性能和更简洁的代码,尤其是在I/O密集型任务(如网络通信、文件读写等)中。然而,线程在处理CPU密集型任务时可能更具优势,因为它们可以利用多核处理器的并行性。不过,要注意不同编程语言和框架对于协程和线程的支持程度可能有所不同,有些语言可能提供了更便捷的协程支持,而有些语言可能更擅长处理线程。

    
public class ListView2Handler<T> where T : class
{
    private List<T> List { get; set; }
    private ListView ListView { get; set; }

    public event ColumnClickEventHandler ColClick;
    public ListView2Handler(ListView listView)
    {
        this.List = new List<T>();
        this.ListView = listView;
        this.ListView.VirtualMode = true;
        this.ListView.RetrieveVirtualItem += ListView_RetrieveVirtualItem;

        this.ListView.ColumnClick += ListView_ColumnClick;
    }

    private void ListView_ColumnClick(object sender, ColumnClickEventArgs e)
    {
        if (this.ColClick != null)
        {
            this.ListView.Sorting = this.ListView.Sorting == SortOrder.Ascending ? SortOrder.Descending : SortOrder.Ascending;
            this.OnColClick(e);
        }
    }

    public virtual void OnColClick(ColumnClickEventArgs e)
    {
        for (int i = 0; i < this.ListView.Columns.Count; i++)
        {
            var text = this.ListView.Columns[i].Text;//
            text = text.Replace("▽", "").Replace("△", "").Trim();

            if (i == e.Column)
            {
                if (this.ListView.Sorting == SortOrder.Ascending)
                {
                    text += "△";
                }
                else
                {
                    text += "▽";
                }
            }
            this.ListView.Columns[i].Text = text;
        }
        this.ListView.AutoResizeColumn(e.Column, ColumnHeaderAutoResizeStyle.HeaderSize);

        this.ColClick?.Invoke(this.ListView, e);
    }


    private void ListView_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
    {
        if (List.Any() && e.ItemIndex <= List.Count)
        {
            var mode = this.List[e.ItemIndex];
            var item = GetListViewItems(mode, e.ItemIndex);
            if (e.ItemIndex % 2 == 0)
            {
                item.BackColor = Color.FromArgb(250, 250, 240);
            }
            e.Item = item;
        }
    }

    public void ShowColumHeader()
    {
        var ps = typeof(T).GetProperties();
        if (ps != null)
        {
            foreach (var p in ps)
            {
                var attr = p.GetCustomAttribute<HanderDescriptionAttribute>();
                if (attr != null)
                {
                    if (attr == null)
                        continue;
                    ColumnHeader header = new ColumnHeader();
                    header.Text = attr.Name;
                    header.Tag = p.Name;
                    ListView.Columns.Add(header);
                }
            }
        }

    }
    public void ClearData()
    {
        List.Clear();
        ListView.Invoke(new MethodInvoker(() =>
        {
            ListView.VirtualListSize = List.Count;
            ListView.Invalidate();
        }));
    }
    public void LoadData(IEnumerable<T> datas)
    {
        ClearData();
        if (datas == null)
            return;
        this.List.AddRange(datas);
        ListView.Invoke(new MethodInvoker(() =>
        {
            ListView.VirtualListSize = List.Count;
            ListView.Invalidate();
            this.ListView.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
        }));
    }
    public void RemoveItem(T item)
    {
        this.List.Remove(item);
        this.ListView.VirtualListSize = List.Count;
        this.ListView.Invalidate();
        //this.listView.Refresh();
    }

    public List<T> Filter(Predicate<T> predicate)
    {
        return this.List.FindAll(predicate);
    }

    //public void Sort(Func<T, object> predicate)
    public void Sort(Func<T, object> func)
    {
        var comparer = new ListViewItemComparer<T>(func, Comparer<object>.Default, this.ListView.Sorting);
        this.List.Sort(comparer);
        this.ListView.Invalidate();
    }

    public void EditData(T objItem)
    {
        var model = this.List.FindIndex(m => m == objItem);
        if (model > -1)
        {
            this.List[model] = objItem;
        }
        this.ListView.Invalidate();

    }
    public ListViewItem GetFouseItem()
    {
        return this.ListView.FocusedItem;
    }

    public T GetSelectData()
    {
        var d = this.ListView.FocusedItem;
        if (d != null)
        {
            return (T)this.ListView.FocusedItem.Tag;
        }
        return default(T);
    }

    public IEnumerable<T> GetSelectValues()
    {
        var ids = this.ListView.SelectedIndices;
        for (int i = 0; i < ids.Count; i++)
        {
            yield return this.List[ids[i]];
        }

    }

    private ListViewItem GetListViewItems(T model, int index)
    {
        var ps = model.GetType().GetProperties();
        var item = new ListViewItem();
        item.Tag = model;
        foreach (var p in ps)
        {
            var da = p.GetCustomAttribute<HanderDescriptionAttribute>();
            if (da == null)
                continue;

            var value = p.GetValue(model);
            if (da.IsPrimary)
            {
                //if (index > 0 && value != null && p.PropertyType == typeof(int))
                //{
                //    p.SetValue(model, index);
                //}

                if (value == null || (value.GetType() == typeof(int) && (int)value == 0))
                {
                    item.Text = index + da?.ExStr;
                    continue;
                }
                item.Text = value?.ToString() + da?.ExStr;
                continue;
            }
            item.SubItems.Add(value?.ToString() + da?.ExStr);
        }

        return item;
    }
}

public class ListViewItemComparer : IComparer
{
    private int col;
    private SortOrder order;
    public ListViewItemComparer(int column, SortOrder sortOrder)
    {
        col = column;
        order = sortOrder;
    }
    public int Compare(object x, object y)
    {
        int returnVal = -1;

        // 按字符串排序
        string strX = ((ListViewItem)x).SubItems[col].Text;
        string strY = ((ListViewItem)y).SubItems[col].Text;

        returnVal = String.Compare(strX, strY);

        // 根据排序方式反转结果
        if (order == SortOrder.Descending)
        {
            returnVal *= -1;
        }

        return returnVal;
    }
}
public class ListViewItemComparer<T> : IComparer<T> where T : class
{
    private Func<T, object> _keySelector;
    private IComparer<object> _valueComparer;
    private readonly SortOrder sortOrder;

    public ListViewItemComparer(Func<T, object> keySelector, IComparer<object> valueComparer, SortOrder sortOrder)
    {
        _keySelector = keySelector;
        _valueComparer = valueComparer;
        this.sortOrder = sortOrder;
    }


    public int Compare(T x, T y)
    {
        object xValue = _keySelector(x);
        object yValue = _keySelector(y);

        var returnVal= _valueComparer.Compare(xValue, yValue);
        // 根据排序方式反转结果
        if (sortOrder == SortOrder.Descending)
        {
            returnVal *= -1;
        }
        return returnVal;
    }
}
public class HanderDescriptionAttribute : Attribute
{
    public string Name { get; set; }
    public bool IsPrimary { get; set; }
    public string ExStr { get; set; }
}